Forum / Guestbook




dld Fri 14 Jun 2019 at 18:23:09
Safety w1209 thermostat UNSAFE => Arduino Thermostat

-
Safety cheap 2 dollar w1209 thermostat UnSafe Not Safe for heating

another use w1209 thermostat with LDR as light dark switch
if you connect an LDR instead of NTC thermistor
you can make a programmable light dependent switch of w1209 thermostat
switch on when light or dark depending on cool or heat setting
a programmable Light sensitive powerswitch

G.. D... Lutjebroeker BloemKoolBoeren zo kun je je F...-ing knalaparaat snachts stil houden voor 2 dollar

if the temperature sensor is broken/disconnected heating will be switched on forever
burning your house / factory down
program code should turn off heating when nonsense or no sensordata
but relais is turned on
also programcode is not checking if there is temperature rise/time when relais is on
should shut down when it sees no rise/time when relais is turned on
maybe an extra parameter maximum continu on time relais if to long on error MMM

when sensor disconnected display shows LLL but does not turn relay off
when sensor shorted display shows HHH but does not turn relay off
sometimes i get --- then relay is turned off, --- is high temp alarm P6 on
Nice DIY importing of cheap Chinese products
and even European companys sell this inferior Chinese products => CONRAD, REICHELT, Etcetera

if you sell hundredthousands of these prints why not make the code safe
https://images-na.ssl-images-amazon.com/images/I/71Y-7iz1lML.pdf
above PDF says it should turn relay off when LLL or HHH
but not on the 2 thermostats i have from aliexpres


make it better?
make an arduino version alike w1209 thermostat?
arduino code like w1209 thermostat?
sourcecode w1209 thermostat?





A SMART GUY FROM INDIA WHO THINKS ABOUT SAFETY
Dual w1209 High temperature shutdown safety English #w1209 #thermostat #temperature
think it would be easyer to use 2 with same setting or safety one a bit heigher
and put relay contacts in series
so for your house temp one at 21degrees celsius and a safety one at 25 degrees celsius
if 21 degrees fails to turn off you have the safety one at 25 degrees to turn series contact off
A SMART GUY FROM INDIA WHO THINKS ABOUT SAFETY

W1209 Function P6 Bug? P6 Fail?
i think that there seems to be a relation between P2 maxsettemp and P6 alarmtemp



make it better?
make an arduino version alike w1209 thermostat?
arduino code like w1209 thermostat?
sourcecode w1209 thermostat?

Arduino thermostat for negative and positive temperature (4)

https://github.com/tehniq3/DS18B20_thermostat_4digit_7segment_led_display/blob/master/4dig7segm_ac_18b20_thermostat_ver4m7.ino

WARNING!
DO NOT power
the LCD and relais board
from the NANO 5vdc voltage regulator
is to much for the NANO!

modify above code to w1209 alike but better
maybe i2c lcd or 2wire 7segment is easyer




or with a NTC thermistor cheaper and nicer values versus ds18b20 (the 0.0625C resulotion hurts my brain)
http://www.circuitbasics.com/arduino-thermistor-temperature-sensor-tutorial/

nice but when i treid this on a nano ntc reading was noisy fluctuating
take 200ormore analogreadings and divide by 200ormore to take the average
thats much better stable
should do this on analogreadings in other projects also

WARNING!
DO NOT power
the LCD and relais board
from the NANO 5vdc voltage regulator
is to much for the NANO!








i used the NTC Thermistor + cable from a w1209 thermostat

2 euro for arduino nano clone
2 euro for 4 relais pcb
\ 4 eeuro for 2x16 or 4x20 iic i2c twi LCD

my arduino w1209 thermostat code project ;-) so far
ntc sensor disconnect and short detection
only prints to terminal
NTC thermistor A0
NO buttons set=D2 +=D3 -=D4 pullup in code
and relais D10
i used a 2 euro Arduino nano clone
thinking of adding LDR powerswitch option map analogread 0...1023 to 0..100
add option LDR darkswitch and LDR lightSwitch






wanted to replace pushbuttons for rotary encoder module pcb
tought that was easy
treid many examples
none worked perfect
but this rotary example code looks promising good
https://www.best-microcontroller-projects.com/rotary-encoder.html
// Robust Rotary encoder reading
// Copyright John Main - best-microcontroller-projects.com
// https://www.best-microcontroller-projects.com/rotary-encoder.html
//
#define CLK 2
#define DATA 3

void setup() {
  pinMode(CLK, INPUT);
  pinMode(CLK, INPUT_PULLUP);
  pinMode(DATA, INPUT);
  pinMode(DATA, INPUT_PULLUP);
  Serial.begin (115200);
  Serial.println("KY-040 Start:");
}

static uint8_t prevNextCode = 0;
static uint16_t store=0;

void loop() {
static float c,val;

   if( val=read_rotary() ) {
      c +=val;
      Serial.print(c);Serial.println(" ");

      if ( prevNextCode==0x0b) {
         //Serial.print("eleven ");
         //Serial.println(store,HEX);
      }

      if ( prevNextCode==0x07) {
         //Serial.print("seven ");
         //Serial.println(store,HEX);
      }
   }
}

// A vald CW or  CCW move returns 1, invalid returns 0.
float read_rotary() {
  static int8_t rot_enc_table[] = {0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0};

  prevNextCode <<= 2;
  if (digitalRead(DATA)) prevNextCode |= 0x02;
  if (digitalRead(CLK)) prevNextCode |= 0x01;
  prevNextCode &= 0x0f;

   // If valid then store as 16 bit data.
   if  (rot_enc_table[prevNextCode] ) {
      store <<= 4;
      store |= prevNextCode;
      //if (store==0xd42b) return 1;
      //if (store==0xe817) return -1;
      if ((store&0xff)==0x2b) return -0.1;
      if ((store&0xff)==0x17) return 0.1;
   }
   return 0;
}
// Robust Rotary encoder reading
// Copyright John Main - best-microcontroller-projects.com
// https://www.best-microcontroller-projects.com/rotary-encoder.html
//





Arduino w1209 thermostat clone
this is the 3 button version
in the future i will use a rotary encoder button
rotary encoder version will be below this



// Do Not be afraid Arduino is fun to play with
// 
// and arduino clones are cheap with loads of cheap components



// Feature request? IF desired settemp not reached within ??? seconds THEN alarm



// version 22-june-2019 12:30
//Sketch uses 15680 bytes (51%) of program storage space. Maximum is 30720 bytes.
//Global variables use 516 bytes (25%) of dynamic memory, leaving 1532 bytes for local variables. Maximum is 2048 bytes.








// version 23-june-2019
// should become a safe arduino version of w1209 thermostat
// but far from finished
// parts of code used from
// http://www.circuitbasics.com/arduino-the<wbr />rmistor-temperature-sensor-tutorial/
// https://github.com/tehniq3/DS18B20_therm<wbr />ostat_4digit_7segment_led_display/blob/m<wbr />aster/4dig7segm_ac_18b20_thermostat_ver4<wbr />m7.ino
//
// this code came from
// http://84.106.2.21:8888/forum/index.php?<wbr />action=view&id=296
// copyright then, now, and forever, luberth dijkman bangert 30 andijk the netherlands
// bob-a-job
// a nickle or dime would be apreciated http://paypal.me/pools/c/8amUN5rgb9
// if you gave me 5 cents for every device you program with this code
// i will be verry happy
// it doesnt hurt
// http://paypal.me/pools/c/8amUN5rgb9
//
// I Feel so lonely in this Universe ;-(
// if you change the program to make it do more or better
// would like to know/share
// https://m.facebook.com/luberth.dijkman
<wbr />// http://84.106.2.21:8888/forum/index.php?<wbr />action=view&id=296


#include <EEPROM.h>
#include <LiquidCrystal_I2C.h>                     // https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/Home
LiquidCrystal_I2C  lcd(0x27, 2, 1, 0, 4, 5, 6, 7);



float Vo;
float R1 = 10000;
float logR2, R2, T, Tc, Tf;
float c1 = 1.009249522e-03, c2 = 2.378405444e-04, c3 = 2.019202697e-07;
float CalibrationOffset = 0; //w1209 thermostat has -7 to +7 0.1 steps

float SwitchOnTemp = 30.0f;
byte TempByte;
float TempFloat;
int TempInt;
unsigned long TempLong;
byte val;
int RelaisState = 0;
byte CoolorHeat = 2; //1=cool 2=heat

int delayval;
float MaxTemp = 110;
float MinTemp = -40;
int LowTempAlarmVal = 0 ;
int HighTempAlarmVal = 100;

float relayonpointbelowsetpoint = -0.2;
float relayoffabovesetpoint = 0.1;

int menu = 0;
unsigned long starttime;
unsigned long timeon;


int MaxTimeRelayMayBeonInSeconds = 600;
int MaxTime2SetPoint = 300;

void setup() {

  //Serial.begin(115200);
  Serial.begin(9600);

  lcd.begin(20, 4);
  lcd.setBacklightPin(3, POSITIVE);
  lcd.setBacklight(HIGH);

  // first time i use eeprom, thought it would be very hard to use
  // i make steps of 5 in eeprom adres because i did not know what to use
  // 5 is a nice step when i look with the eeprom read example from arduino
  // not optimal use of eeprom but have eeprom more then i use

  /*
    // next is for test => normally commented
    // erase eeprom all to 0
        for (int i = 0 ; i < EEPROM.length() ; i++){EEPROM.put(i, 0);
                            //was eeprom.write but i think put is better   put only writes when val not the same
            lcd.setCursor(2, 1);lcd.print(i);lcd.print(" Erase EEPROM");
        } // erase eeprom all to 0
       for (int i = 30 ; i > 0 ; i--){lcd.setCursor(9, 3);lcd.print(i);lcd.print(" ");delay(500);}
    // erase eeprom all to 0
  */


  // first run ??? write some val to eeprom if value at eepromadres 666 not is 666
  //if this is first run then val will not be 666 at eeprom adres 666 so next will be run
  EEPROM.get(666, TempInt);
  if (TempInt != 666) {           // IF this is the first run THEN val at eeprom adres 666 is -1???
    EEPROM.put(0, 31.00);         // setpoint
    EEPROM.put(5, 0.00);          // callibration offset
    EEPROM.put(10, -0.3);         // below on
    EEPROM.put(15, 0.3);          // above off
    EEPROM.put(20, 600);          // max time in seconds relay on
    EEPROM.put(25, 2);            // 1 cool 2 heat
    EEPROM.put(30, 90);           // high temp alarm
    EEPROM.put(35, 20);           // low temp alarm
    EEPROM.put(40, 300);
    EEPROM.put(666, 666);        // set eepromadres 666 to val 666 no need to call / run this anymore in future
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print(F("Hi There! First run"));
    lcd.setCursor(0, 1);
    lcd.print(F("Have written value's"));
    lcd.setCursor(0, 2);
    lcd.print(F("to EEPROM "));
    lcd.setCursor(0, 3);
    lcd.print(F("Thanks for trying"));
    for (int i = 30 ; i > 0 ; i--) {
      lcd.setCursor(17, 2);
      lcd.print(i);
      lcd.print(" ");
      delay(500);
    }
    lcd.clear();
  }


  // is written in eeprom like this
  // 665 255
  // 666 154       2x256+154=666
  // 667 2
  // 668 255
  /*
    0 30
    1 0
    2 240
    3 65
    4 255
    5 0
    6 0
    7 128
    8 178
    9 255
    10  154
    11  153
    12  153
    13  190
    14  255
    15  154
    16  153
    17  153
    18  62
    19  255
    20  88
    21  2
    22  255
    23  255
    24  255
    25  255
    26  255
    27  255
    28  255
    29  255
    30  90
    31  0
    32  255
    33  255
    34  255
    35  20
    36  0
    37  255
    38  255
    39  255
    40  255
  */




  // read stored valeus from eeprom
  EEPROM.get(0, SwitchOnTemp);
  EEPROM.get(5, CalibrationOffset);
  EEPROM.get(10, relayonpointbelowsetpoint);
  EEPROM.get(15, relayoffabovesetpoint);
  EEPROM.get(20, MaxTimeRelayMayBeonInSeconds);
  EEPROM.get(25, CoolorHeat);
  EEPROM.get(30, HighTempAlarmVal);
  EEPROM.get(35, LowTempAlarmVal);
  EEPROM.get(40, MaxTime2SetPoint);

  // A0 NTC thermistor
  pinMode(2, INPUT_PULLUP);       // set button
  pinMode(3, INPUT_PULLUP);       // + button
  pinMode(4, INPUT_PULLUP);       // - button
  pinMode(10, OUTPUT);            // relais
  pinMode(11, OUTPUT);            // lowtemp alarm relais
  pinMode(12, OUTPUT);            // hightemp alarm relais
  pinMode(13, OUTPUT);            // another relais
}




void loop() {

  // int SetButton() = SetButton();
  // int PlusButton = PlusButton();
  // int MinButton = MinButton();

  if (SetButton() == LOW) {
    menu = 1;
    while (SetButton() == LOW) {
      // loop until button released
      // maybe a timer here
      // alarm if button never released
    }
    lcd.clear();
  }



  //1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
  //setpoint setpoint setpoint setpoint setpoint setpoint setpoint setpoint setpoint setpoint setpoint setpoint setpoint setpoint 
  TempLong = millis();  //reset innactive time counter
  while (menu == 1) {
    if ((millis() - TempLong) / 1000 > 20) {
      TimeOut();
      break;
    }
    delayval = 150;
    while (PlusButton() == LOW) {
      TempLong = millis();  //reset innactive time counter
      SwitchOnTemp = SwitchOnTemp + 0.1;
      if (SwitchOnTemp > MaxTemp) {
        SwitchOnTemp = MaxTemp;
        Serial.println(F("Reached MaxTemp"));
      }
      delay(delayval);
      delayval = delayval - 2;
      if (  delayval < 1)  delayval = 1;
      //Serial.println("menu 1 ");
      Serial.print(F("SwitchOnTemp "));
      Serial.println(SwitchOnTemp);
      lcd.setCursor(0, 1);
      lcd.print(SwitchOnTemp);
      lcd.print(F(" "));
    }
    while (MinButton() == LOW) {
      TempLong = millis();  //reset innactive time counter
      SwitchOnTemp = SwitchOnTemp - 0.1;
      if (SwitchOnTemp < MinTemp) {
        SwitchOnTemp = MinTemp;
        Serial.println(F("Reached MinTemp "));
      }
      delay(delayval);
      delayval = delayval - 2;
      if (  delayval < 1)  delayval = 1;
      //Serial.println("menu 1 ");
      Serial.print(F("SwitchOnTemp "));
      Serial.println(SwitchOnTemp);
      lcd.setCursor(0, 1);
      lcd.print(SwitchOnTemp);
      lcd.print(F(" "));
    }
    //Serial.println("menu 1 ");
    Serial.print(F("SwitchOnTemp "));
    Serial.println(SwitchOnTemp);
    lcd.setCursor(0, 0);
    lcd.print(F("1 SetTemp"));
    lcd.setCursor(0, 1);
    lcd.print(SwitchOnTemp);
    lcd.print(F(" "));

    if (SetButton() == LOW) {
      menu = 2;
      lcd.clear();
      delay(250);
    }
  }


  EEPROM.get(0, TempFloat);                         // limmited write to eeprom = read is unlimmited
  if (SwitchOnTemp != TempFloat) {                  // only write to eeprom if value is different
    EEPROM.put(0, SwitchOnTemp);                    // put already checks if val is needed to write
    lcd.setCursor(0, 0);
    lcd.print(F("Saving to EEPROM"));
    lcd.setCursor(0, 2);
    lcd.print(TempFloat);
    lcd.print(F(" new= "));
    lcd.print(SwitchOnTemp);

    for (int i = 0; i < 100; i++)Serial.println(F("SwitchOnTemp DATA WRITEN / SAVED TO EEPROM "));
    lcd.clear();
  }






  //2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 
  //calibration calibration calibration calibration calibration calibration calibration calibration calibration calibration calibration 
  TempLong = millis();  //reset innactive time counter
  while (menu == 2) {
    if ((millis() - TempLong) / 1000 > 20) {
      TimeOut();
      break;
    }
    if (PlusButton() == LOW) {
      TempLong = millis();  //reset innactive time counter
      CalibrationOffset = CalibrationOffset + 0.1;
      if (CalibrationOffset > 7)CalibrationOffset = 7;
      delay(200);
    }
    if (MinButton() == LOW) {
      TempLong = millis();  //reset innactive time counter
      CalibrationOffset = CalibrationOffset - 0.1;
      if (CalibrationOffset < -7)CalibrationOffset = -7;
      delay(200);
    }
    //Serial.println("menu 2 ");
    Serial.print(F("CalibrationOffset "));
    Serial.println(CalibrationOffset);
    lcd.setCursor(0, 0);
    lcd.print(F("2 Cal. Offset"));
    lcd.setCursor(0, 1);
    lcd.print(CalibrationOffset);
    lcd.print(F(" "));

    if (SetButton() == LOW) {
      menu = 3;
      lcd.clear();
      delay(250);
    }
  }

  EEPROM.get(5, TempFloat);                         // limmited write to eeprom = read is unlimmited
  if (CalibrationOffset != TempFloat) {             // only write to eeprom if value is different
    EEPROM.put(5, CalibrationOffset);               // i have no idea wat eeprom adress to use just jump to 5
    lcd.setCursor(0, 0);
    lcd.print(F("Saving to EEPROM"));
    lcd.setCursor(0, 2);
    lcd.print(TempFloat);
    lcd.print(F(" new= "));
    lcd.print(CalibrationOffset);
    for (int i = 0; i < 100; i++)Serial.println(F("CalibrationOffset DATA WRITEN / SAVED TO EEPROM "));
    lcd.clear();
  }

  //3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 
  //below set below set below set below set below set below set below set below set below set below set below set below set below set 
  TempLong = millis();  //reset innactive time counter
  while (menu == 3) {
    if ((millis() - TempLong) / 1000 > 20) {
      TimeOut();
      break;
    }
    if (PlusButton() == LOW) {
      TempLong = millis();  //reset innactive time counter
      relayonpointbelowsetpoint = relayonpointbelowsetpoint + 0.1;
      if (relayonpointbelowsetpoint > -0.1)relayonpointbelowsetpoint = -0.1;
      delay(50);
    }
    if (MinButton() == LOW) {
      TempLong = millis();  //reset innactive time counter
      relayonpointbelowsetpoint = relayonpointbelowsetpoint - 0.1;
      if (relayonpointbelowsetpoint < -2)relayonpointbelowsetpoint = -2;
      delay(50);
    }

    //Serial.println("menu 3 ");
    Serial.print(F("relayonpointbelowsetpoint "));
    Serial.println(relayonpointbelowsetpoint);
    lcd.setCursor(0, 0);
    lcd.print(F("3 Below Set"));
    lcd.setCursor(0, 1);
    lcd.print(relayonpointbelowsetpoint);
    lcd.print(F(" "));

    if (SetButton() == LOW) {
      menu = 4;
      lcd.clear();
      delay(250);
    }
  }

  EEPROM.get(10, TempFloat);                         // limmited write to eeprom = read is unlimmited
  if (relayonpointbelowsetpoint != TempFloat) {             // only write to eeprom if value is different
    EEPROM.put(10, relayonpointbelowsetpoint);               // i have no idea wat eeprom adress to use just jump to 10
    lcd.setCursor(0, 0);
    lcd.print(F("Saving to EEPROM"));
    lcd.setCursor(0, 2);
    lcd.print(TempFloat);
    lcd.print(F(" new= "));
    lcd.print(relayonpointbelowsetpoint);
    for (int i = 0; i < 100; i++)Serial.println(F("relayonpointbelowsetpoint DATA WRITEN / SAVED TO EEPROM "));
    lcd.clear();
  }


  //4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 
  //above set above set above set above set above set above set above set above set above set above set above set above set 
  TempLong = millis();  //reset innactive time counter
  while (menu == 4) {
    if ((millis() - TempLong) / 1000 > 20) {
      TimeOut();
      break;
    }
    if (PlusButton() == LOW) {
      TempLong = millis();  //reset innactive time counter
      relayoffabovesetpoint = relayoffabovesetpoint + 0.1;
      if (relayoffabovesetpoint > 2)relayoffabovesetpoint = 2;
      delay(50);
    }
    if (MinButton() == LOW) {
      TempLong = millis();  //reset innactive time counter
      relayoffabovesetpoint = relayoffabovesetpoint - 0.1;
      if (relayoffabovesetpoint < 0)relayoffabovesetpoint = 0;
      delay(50);
    }

    //Serial.println("menu 3 ");
    Serial.print(F("relayoffabovesetpoint "));
    Serial.println(relayoffabovesetpoint);
    lcd.setCursor(0, 0);
    lcd.print(F("4 Above Set"));
    lcd.setCursor(0, 1);
    lcd.print(relayoffabovesetpoint);
    lcd.print(F(" "));

    if (SetButton() == LOW) {
      menu = 5;
      delay(250);
    }
  }

  EEPROM.get(15, TempFloat);                         // limmited write to eeprom = read is unlimmited
  if (relayoffabovesetpoint != TempFloat) {             // only write to eeprom if value is different
    EEPROM.put(15, relayoffabovesetpoint);               // i have no idea wat eeprom adress to use just jump to 5
    lcd.setCursor(0, 0);
    lcd.print(F("Saving to EEPROM"));
    lcd.setCursor(0, 2);
    lcd.print(TempFloat);
    lcd.print(F(" new= "));
    lcd.print(relayoffabovesetpoint);
    for (int i = 0; i < 100; i++)Serial.println(F("relayoffabovesetpoint DATA WRITEN / SAVED TO EEPROM "));
    lcd.clear();
  }

  //5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 
  //max t relay max t relay max t relay max t relay max t relay max t relay max t relay max t relay max t relay max t relay 
  TempLong = millis();  //reset innactive time counter
  while (menu == 5) {
    if ((millis() - TempLong) / 1000 > 20) {
      TimeOut();
      break;
    }
    if (PlusButton() == LOW) {
      TempLong = millis();  //reset innactive time counter
      MaxTimeRelayMayBeonInSeconds = MaxTimeRelayMayBeonInSeconds + 1;
      if (MaxTimeRelayMayBeonInSeconds > 3600)MaxTimeRelayMayBeonInSeconds = 3600;
      delay(50);
    }
    if (MinButton() == LOW) {
      TempLong = millis();  //reset innactive time counter
      MaxTimeRelayMayBeonInSeconds = MaxTimeRelayMayBeonInSeconds - 1;
      if (MaxTimeRelayMayBeonInSeconds < 30)MaxTimeRelayMayBeonInSeconds = 30;
      delay(50);
    }

    Serial.print(F("maximum time the relay may be on in seconds "));
    Serial.println(MaxTimeRelayMayBeonInSeconds);
    lcd.setCursor(0, 0);
    lcd.print(F("5 Max T Relay on Sec"));
    lcd.setCursor(0, 1);
    lcd.print(MaxTimeRelayMayBeonInSeconds);
    lcd.print(F(" "));

    if (SetButton() == LOW) {
      menu = 6;
      lcd.clear();
      delay(250);
    }
  }

  EEPROM.get(20, TempInt);                         // limmited write to eeprom = read is unlimmited
  if (MaxTimeRelayMayBeonInSeconds != TempInt) {             // only write to eeprom if value is different
    EEPROM.put(20, MaxTimeRelayMayBeonInSeconds);               // i have no idea wat eeprom adress to use just jump to 10
    lcd.setCursor(0, 0);
    lcd.print(F("Saving to EEPROM"));
    lcd.setCursor(0, 2);
    lcd.print(TempInt);
    lcd.print(F(" new= "));
    lcd.print(MaxTimeRelayMayBeonInSeconds);
    for (int i = 0; i < 100; i++)Serial.println(F("MaxTimeRelayMayBeonInSeconds DATA WRITEN / SAVED TO EEPROM "));
    lcd.clear();
  }

  //6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 
  //CoolorHeat CoolorHeat CoolorHeat CoolorHeat CoolorHeat CoolorHeat
  TempLong = millis();  //reset innactive time counter
  while (menu == 6) {
    if ((millis() - TempLong) / 1000 > 20) {
      TimeOut();
      break;
    }
    if (PlusButton() == LOW) {
      TempLong = millis();  //reset innactive time counter
      CoolorHeat = CoolorHeat + 1;
      if (CoolorHeat > 2)CoolorHeat = 1;
      delay(250);
    }
    if (MinButton() == LOW) {
      TempLong = millis();  //reset innactive time counter
      CoolorHeat = CoolorHeat - 1;
      if (CoolorHeat < 1)CoolorHeat = 2;
      delay(250);
    }

    Serial.println(F("cool / heat / ldr on dark / ldr on light "));
    //Serial.println(SwitchOnTemp);
    lcd.setCursor(0, 0);
    lcd.print(F("6 Cool / Heat"));
    lcd.setCursor(0, 1);
    if (CoolorHeat == 1)lcd.print(F("Not yet! = COOL"));
    if (CoolorHeat == 2)lcd.print(F("Not yet! = HEAT"));

    if (SetButton() == LOW) {
      menu = 7;
      lcd.clear();
      delay(250);
    }
  }

  EEPROM.get(25, TempByte);                         // limmited write to eeprom = read is unlimmited
  if (CoolorHeat != TempByte) {                     // only write to eeprom if value is different
    EEPROM.put(25, CoolorHeat);                     // i have no idea wat eeprom adress to use just jump to 10
    lcd.setCursor(0, 0);
    lcd.print(F("Saving to EEPROM"));
    lcd.setCursor(0, 2);
    lcd.print(TempByte);
    lcd.print(F(" new= "));
    if (CoolorHeat == 1)lcd.print(F("COOL"));
    if (CoolorHeat == 2)lcd.print(F("HEAT"));
    for (int i = 0; i < 100; i++)Serial.println(F("Cool/Heat DATA WRITEN / SAVED TO EEPROM "));
    lcd.clear();
  }







  //777777777777777777777777777777777777777777777777777777777777777777777
  TempLong = millis();  //reset innactive time counter
  while (menu == 7) {
    if ((millis() - TempLong) / 1000 > 20) {
      TimeOut();
      break;
    }
    if (PlusButton() == LOW) {
      TempLong = millis();  //reset innactive time counter
      HighTempAlarmVal = HighTempAlarmVal + 1;
      if (HighTempAlarmVal > MaxTemp)HighTempAlarmVal = MaxTemp;
      delay(50);
    }
    if (MinButton() == LOW) {
      TempLong = millis();  //reset innactive time counter
      HighTempAlarmVal = HighTempAlarmVal - 1;
      if (HighTempAlarmVal < MinTemp)HighTempAlarmVal = MinTemp;
      delay(50);
    }

    Serial.print(F("High Temp alarm  "));
    Serial.println(HighTempAlarmVal);
    lcd.setCursor(0, 0);
    lcd.print(F("7 High Temp Alarm"));
    lcd.setCursor(0, 1);
    lcd.print(HighTempAlarmVal );
    lcd.print(F(" "));

    if (SetButton() == LOW) {
      menu = 8;
      lcd.clear();
      delay(250);
    }
  }

  EEPROM.get(30, TempInt);                         // limmited write to eeprom = read is unlimmited
  if (HighTempAlarmVal != TempInt) {             // only write to eeprom if value is different
    EEPROM.put(30, HighTempAlarmVal);               // i have no idea wat eeprom adress to use just jump to 10
    lcd.setCursor(0, 0);
    lcd.print(F("Saving to EEPROM"));
    lcd.setCursor(0, 2);
    lcd.print(TempInt);
    lcd.print(F(" new= "));
    lcd.print(HighTempAlarmVal);
    for (int i = 0; i < 100; i++)Serial.println(F("HighTempAlarmVal DATA WRITEN / SAVED TO EEPROM "));
    lcd.clear();
  }

  //888888888888888888888888888888888888888888888888888888888888888888888888888888
  TempLong = millis();  //reset innactive time counter
  while (menu == 8) {
    if ((millis() - TempLong) / 1000 > 20) {
      TimeOut();
      break;
    }
    if (PlusButton() == LOW) {
      TempLong = millis();  //reset innactive time counter
      LowTempAlarmVal = LowTempAlarmVal + 1;
      if (LowTempAlarmVal > MaxTemp)LowTempAlarmVal = MaxTemp;
      delay(250);
    }
    if (MinButton() == LOW) {
      TempLong = millis();  //reset innactive time counter
      LowTempAlarmVal = LowTempAlarmVal - 1;
      if (LowTempAlarmVal < MinTemp)LowTempAlarmVal = MinTemp;
      delay(250);
    }

    Serial.print(F("Low Temp alarm  "));
    Serial.println(LowTempAlarmVal);
    lcd.setCursor(0, 0);
    lcd.print(F("8 Low Temp Alarm"));
    lcd.setCursor(0, 1);
    lcd.print(LowTempAlarmVal );
    lcd.print(F(" "));

    if (SetButton() == LOW) {
      menu = 9;
      lcd.clear();
      delay(250);
    }
  }


  EEPROM.get(35, TempInt);                         // limmited write to eeprom = read is unlimmited
  if (LowTempAlarmVal != TempInt) {             // only write to eeprom if value is different
    EEPROM.put(35, LowTempAlarmVal);               // i have no idea wat eeprom adress to use just jump to 10
    lcd.setCursor(0, 0);
    lcd.print(F("Saving to EEPROM"));
    lcd.setCursor(0, 2);
    lcd.print(TempInt);
    lcd.print(F(" new= "));
    lcd.print(LowTempAlarmVal);
    for (int i = 0; i < 100; i++)Serial.println(F("LowTempAlarmVal DATA WRITEN / SAVED TO EEPROM "));
    lcd.clear();
  }




  //9999999999999999999999999999999999999999999999999999999999999999999999999999999999999
  TempLong = millis();  //reset innactive time counter
  while (menu == 9) {
    if ((millis() - TempLong) / 1000 > 20) {
      TimeOut();
      break;
    }
    if (PlusButton() == LOW) {
      TempLong = millis();  //reset innactive time counter
      MaxTime2SetPoint = MaxTime2SetPoint + 1;
      if (MaxTime2SetPoint > MaxTimeRelayMayBeonInSeconds)MaxTime2Set<wbr />Point = MaxTimeRelayMayBeonInSeconds;
      delay(200);
    }
    if (MinButton() == LOW) {
      TempLong = millis();  //reset innactive time counter
      MaxTime2SetPoint = MaxTime2SetPoint - 1;
      if (MaxTime2SetPoint < 0)MaxTime2SetPoint = 0;
      delay(200);
    }

    Serial.print(F("MaxTime2SetPoint  "));
    Serial.println(MaxTime2SetPoint);
    lcd.setCursor(0, 0);
    lcd.print(F("9 MaxTime2SetPoint"));
    lcd.setCursor(0, 1);
    lcd.print(MaxTime2SetPoint );
    lcd.print(F(" "));

    if (SetButton() == LOW) {
      menu = 10;
      lcd.clear();
      delay(250);
    }
  }


  EEPROM.get(40, TempInt);                         // limmited write to eeprom = read is unlimmited
  if (MaxTime2SetPoint != TempInt) {             // only write to eeprom if value is different
    EEPROM.put(40, MaxTime2SetPoint);               // i have no idea wat eeprom adress to use just jump to 10
    lcd.setCursor(0, 0);
    lcd.print(F("Saving to EEPROM"));
    lcd.setCursor(0, 2);
    lcd.print(TempInt);
    lcd.print(F(" new= "));
    lcd.print(MaxTime2SetPoint);
    for (int i = 0; i < 100; i++)Serial.println(F("MaxTime2SetPoint DATA WRITEN / SAVED TO EEPROM "));
    lcd.clear();
  }





  //10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10
  TempLong = millis();  //reset innactive time counter
  while (menu == 10) {
    if ((millis() - TempLong) / 1000 > 20) {
      TimeOut();
      break;
    }
    if (PlusButton() == LOW && MinButton() == LOW) {
      EEPROM.put(0, 30.00);         // setpoint
      EEPROM.put(5, 0.00);          // callibration offset
      EEPROM.put(10, -0.3);         // below on
      EEPROM.put(15, 0.3);          // above off
      EEPROM.put(20, 600);          // max time in seconds relay on
      EEPROM.put(25, 2);            // 1=cool 2=heat
      EEPROM.put(30, 90);           // high temp alarm
      EEPROM.put(35, 20);           // low temp alarm
      EEPROM.put(40, 300);
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print(F("Saving to EEPROM"));
      for (int i = 0; i < 100; i++)Serial.println(F(" valeus restored to factory settings "));
      // read stored valeus from eeprom
      EEPROM.get(0, SwitchOnTemp);
      EEPROM.get(5, CalibrationOffset);
      EEPROM.get(10, relayonpointbelowsetpoint);
      EEPROM.get(15, relayoffabovesetpoint);
      EEPROM.get(20, MaxTimeRelayMayBeonInSeconds);
      EEPROM.get(25, CoolorHeat);
      EEPROM.get(30, HighTempAlarmVal);
      EEPROM.get(35, LowTempAlarmVal);
      EEPROM.get(40, MaxTime2SetPoint);
      delay(250);
      menu = 11;
    }

    Serial.println(F(" factory reset press + and -   or SetButton() to exit menu"));
    lcd.setCursor(0, 0);
    lcd.print(F("10 Factory Reset"));
    lcd.setCursor(0, 1);
    lcd.print(F("+ & - to Reset"));
    lcd.setCursor(0, 2);
    lcd.print(F("SET = Exit Menu"));

    if (SetButton() == LOW) {
      menu = 11;
      lcd.clear();
      delay(250);
    }
    if (menu == 11) {
      lcd.clear();
      break;
    }
  }





  //11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11
  TempLong = millis();  //reset innactive time counter
  while (menu == 11) {
    if ((millis() - TempLong) / 1000 > 20) {
      TimeOut();
      break;
    }
    //runtime since boot/start days hours minutes seconds
    Serial.println(F(" rumtime menu"));
    lcd.setCursor(0, 0);
    lcd.print(F("10 RunTime"));
    lcd.setCursor(3, 2);
    lcd.print((millis() / 86400000) % 365);
    lcd.print(" ");
    lcd.print((millis() / 3600000) % 24);
    lcd.print(":");
    lcd.print((millis() / 60000) % 60);
    lcd.print(":");
    lcd.print((millis() / 1000) % 60);
    lcd.print("  ");


    if (SetButton() == LOW) {
      menu = 0;
      lcd.clear();
      delay(250);
    }

  }





  Read_NTC_Thermistor();

  //Vo = analogRead(ThermistorPin);
  R2 = R1 * (1023.0 / (float)Vo - 1.0);
  logR2 = log(R2);
  T = (1.0 / (c1 + c2 * logR2 + c3 * logR2 * logR2 * logR2));
  Tc = T - 273.15 + CalibrationOffset;

  //Tf = (Tc * 9.0)/ 5.0 + 32.0; // fahrenheit



  // compare actualtemp to switchpoint with offsets

  if (Tc < SwitchOnTemp + relayonpointbelowsetpoint) {
    RelaisState = 1;
  }
  if (Tc > SwitchOnTemp + relayoffabovesetpoint) {
    RelaisState = 0;
  }


  if (Tc < LowTempAlarmVal) {
    for (int i = 0; i < 10; i++)Serial.println(F(" Alarm Temperature LOW "));
    lcd.setCursor(2, 2);
    lcd.print(F("Alarm Temp. LOW"));

    digitalWrite(11, 1);
  } else {
    digitalWrite(11, 0);

  }

  if (Tc > HighTempAlarmVal) {
    for (int i = 0; i < 10; i++)Serial.println(F(" Alarm Temperature HIGH "));
    digitalWrite(12, 1);
    lcd.setCursor(2, 2);
    lcd.print(F("Alarm Temp. High"));

  } else {
    digitalWrite(12, 0);
  }




  Serial.print(F("D10 "));
  Serial.print(RelaisState);

  Serial.print(F(" A0 "));
  Serial.print(Vo);
  Serial.print(F(" Temp "));
  Serial.print(Tc, 1);  // 1 decimal

  lcd.setCursor(2, 1);
  lcd.print(Tc, 1);
  lcd.print("\337C");//Cdegree sign


  if (Vo <= 60) {
    for (int i = 0; i < 10; i++)Serial.println(F(" analogread < 60 ERROR LOW "));
    RelaisState = 0; //turn off relays
    lcd.setCursor(2, 2);
    lcd.print(F("Alarm sensor low?"));
  }
  if (Vo >= 960) {
    for (int i = 0; i < 10; i++)Serial.println(F(" analogread > 960 ERROR HIGH "));
    RelaisState = 0; //turn off relays
    lcd.setCursor(2, 2);
    lcd.print(F("Alarm sensor high?"));

  }



  //Serial.print("menu nr ");
  //Serial.print(menu);

  Serial.print(F(" Set "));
  Serial.print(SwitchOnTemp);
  lcd.setCursor(10, 1);
  lcd.print(SwitchOnTemp, 1);
  lcd.print("\337C");   //Cdegree sign


  //Serial.print(" TempFloat ");
  //Serial.print(TempFloat);
  //Serial.print(" TempInt ");
  //Serial.print(TempInt);
  //Serial.print(" TempLong ");
  //Serial.print(TempLong);

  Serial.print(F(" Below "));
  Serial.print(relayonpointbelowsetpoint);<wbr />
  Serial.print(F(" Above "));
  Serial.print(relayoffabovesetpoint);

<wbr />
  Serial.print(F(" Offset "));
  Serial.print(CalibrationOffset);

  Serial.print(F(" Lalarm "));
  Serial.print(LowTempAlarmVal);
  Serial.print(F(" Halarm "));
  Serial.print(HighTempAlarmVal);

  if (RelaisState == 0) {
    digitalWrite(10, 0);
    starttime = millis();
  }
  if (RelaisState == 1 && digitalRead(10) == 0) {
    digitalWrite(10, 1);
    starttime = millis();
  }

  timeon =  (millis() - starttime) / 1000;
  Serial.print(F(" MaxT "));
  Serial.print(MaxTimeRelayMayBeonInSecond<wbr />s);

  Serial.print(F(" Ton "));
  Serial.print(timeon);

  if (RelaisState == 1 ) {
    lcd.setCursor(0, 4);
    lcd.print(timeon);
    lcd.print(F(" Sec. Relay ON "));
  } else {
    lcd.setCursor(0, 4);
    lcd.print(F("Relay OFF        "));
  }

  EEPROM.get(666, TempInt);
  Serial.print(F(" Devil "));
  Serial.println(TempInt);


  if (timeon > MaxTimeRelayMayBeonInSeconds) {            //if there is a sensor fail or heating fail
    for (int i = 0; i < 10; i++)Serial.println(F(" >>>>>>>> ERROR max time relay ON <<<<<<<<<"));
    //shutdown more??? relay should not be on so long
    lcd.setCursor(1, 2);
    lcd.print(F("Max Time Relay ON"));
    delay(500);
    lcd.setCursor(1, 2);
    lcd.print(F("                 "));
  }

  if (timeon > MaxTime2SetPoint) {            //
    for (int i = 0; i < 10; i++)Serial.println(F(" >>>>>>>> time on 2 desired setpoint to long <<<<<<<<<"));
    //shutdown more??? relay should not be on so long
    lcd.setCursor(1, 2);
    lcd.print(F("Warning heat time >"));
    delay(500);
    lcd.setCursor(1, 2);
    lcd.print(F("                   "));

  }



  //delay(50);

  // if you change the program to make it do more or better
  // would like to know/share
  // https://m.facebook.com/luberth.dijkman
  // http://84.106.2.21:8888/forum/index.php?<wbr />action=view&id=296

}
//end loop







//maybe above code is better to read if i do button digitalread like this
boolean SetButton() {
  boolean sval;
  sval = digitalRead(2);
  Serial.print(F("SetButton="));
  Serial.println(sval);
  return sval;
}

boolean PlusButton() {
  boolean sval;
  sval = digitalRead(3);
  Serial.print(F("PlusButton="));
  Serial.println(sval);
  return sval;
}

boolean MinButton() {
  boolean sval;
  sval = digitalRead(4);
  Serial.print(F("MinButton="));
  Serial.println(sval);
  return sval;
}

int Read_NTC_Thermistor() {
  for (int i = 0; i < 500; i++) {
    Vo = Vo + analogRead(A0);             // found temp value displayed bouncy noisy fluctuating
    delay(1);                             // do 500 analog ntc readings and divide by 200 to get an average
  }
  Vo = Vo / 500;
  return Vo;
}


void TimeOut() {
  lcd.clear();  //exit menu if 20 seconds innactive
  lcd.setCursor(0, 1);
  lcd.print(F("TimeOut"));
  lcd.setCursor(0, 2);
  lcd.print(F("Return to Mainscreen"));
  delay(2000);
  lcd.clear();
  menu = 0;
}



// it is mostly air i live on
// but i could use your support
// a nickle or dime for every device you put this code on
// would be appreciated http://paypal.me/pools/c/8amUN5rgb9
// more is allowed
  
  
  




1 euro rotary push button encoder and 50 cent KY-013 NTC thermistor module

Arduino w1209 thermostat clone
this is the rotary encoder button version
in the future i will use a rotary encoder button
just a 1 euro pcb module is easier






Arduino w1209 thermostat clone<br>
<b>this is the rotary encoder button version<br>
in the future i will use a rotary encoder button<br>
just a 1 euro pcb module is easier</b>

a quick change to rotary encoder push button <br>
most should work

//version 24june 2019
//
// uno or nano 
// 20x4 i2c lcd
// rotary encoder with pushbutton on axis
// 10k NTC thermistor with 10k resistor
//
// should become a safe arduino version of w1209 thermostat
// but far from finished
// parts of code used from
// http://www.circuitbasics.com/arduino-the<wbr />rmistor-temperature-sensor-tutorial/
// https://github.com/tehniq3/DS18B20_therm<wbr />ostat_4digit_7segment_led_display/blob/m<wbr />aster/4dig7segm_ac_18b20_thermostat_ver4<wbr />m7.ino
// Robust Rotary encoder reading
// Copyright John Main - best-microcontroller-projects.com
// https://www.best-microcontroller-project<wbr />s.com/rotary-encoder.html
//
// this code came from
// http://84.106.2.21:8888/forum/index.php?<wbr />action=view&id=296
// copyright then, now, and forever, luberth dijkman bangert 30 andijk the netherlands
// bob-a-job
// a nickle or dime would be apreciated http://paypal.me/pools/c/8amUN5rgb9
// if you gave me 5 cents for every device you program with this code
// i will be verry happy
// it doesnt hurt
// http://paypal.me/pools/c/8amUN5rgb9
//
// I Feel so lonely in this Universe ;-(
// if you change the program to make it do more or better
// would like to know/share
// https://m.facebook.com/luberth.dijkman
<wbr />// http://84.106.2.21:8888/forum/index.php?<wbr />action=view&id=296


#include <EEPROM.h>
#include <LiquidCrystal_I2C.h>                     // https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/Home
LiquidCrystal_I2C  lcd(0x27, 2, 1, 0, 4, 5, 6, 7);

float Vo;
float R1 = 10000;
float logR2, R2, T, Tc, Tf;
float c1 = 1.009249522e-03, c2 = 2.378405444e-04, c3 = 2.019202697e-07;
float CalibrationOffset = 0; //w1209 thermostat has -7 to +7 0.1 steps

float SwitchOnTemp = 30.0f;
byte TempByte;
float TempFloat;
int TempInt;
unsigned long TempLong;
byte val;
int RelaisState = 0;
byte CoolorHeat = 2; //1=cool 2=heat

int delayval;
float MaxTemp = 110;
float MinTemp = -40;
int LowTempAlarmVal = 0 ;
int HighTempAlarmVal = 100;

float relayonpointbelowsetpoint = -0.2;
float relayoffabovesetpoint = 0.1;

int menu = 0;
unsigned long starttime;
unsigned long timeon;

int MaxTimeRelayMayBeonInSeconds = 600;
int MaxTime2SetPoint = 300;

// Robust Rotary encoder reading
// Copyright John Main - best-microcontroller-projects.com
#defi<wbr />ne CLK 3
#define DATA 4
static uint8_t prevNextCode = 0;
static uint16_t store = 0;

int yesorno; //factory reset




void setup() {

  //Serial.begin(115200);
  Serial.begin(9600);

  lcd.begin(20, 4);
  lcd.setBacklightPin(3, POSITIVE);
  lcd.setBacklight(HIGH);

  // first time i use eeprom, thought it would be very hard to use
  // i make steps of 5 in eeprom adres because i did not know what to use
  // 5 is a nice step when i look with the eeprom read example from arduino
  // not optimal use of eeprom but have eeprom more then i use

  /*
    // next is for test => normally commented
    // erase eeprom all to 0
        for (int i = 0 ; i < EEPROM.length() ; i++){EEPROM.put(i, 0);
                            //was eeprom.write but i think put is better   put only writes when val not the same
            lcd.setCursor(2, 1);lcd.print(i);lcd.print(" Erase EEPROM");
        } // erase eeprom all to 0
       for (int i = 30 ; i > 0 ; i--){lcd.setCursor(9, 3);lcd.print(i);lcd.print(" ");delay(500);}
    // erase eeprom all to 0
  */


  // first run ??? write some val to eeprom if value at eepromadres 666 not is 666
  //if this is first run then val will not be 666 at eeprom adres 666 so next will be run
  EEPROM.get(666, TempInt);
  if (TempInt != 666) {           // IF this is the first run THEN val at eeprom adres 666 is -1???
    EEPROM.put(0, 31.00);         // setpoint
    EEPROM.put(5, 0.00);          // callibration offset
    EEPROM.put(10, -0.3);         // below on
    EEPROM.put(15, 0.3);          // above off
    EEPROM.put(20, 600);          // max time in seconds relay on
    EEPROM.put(25, 2);            // 1 cool 2 heat
    EEPROM.put(30, 90);           // high temp alarm
    EEPROM.put(35, 20);           // low temp alarm
    EEPROM.put(40, 300);
    EEPROM.put(666, 666);        // set eepromadres 666 to val 666 no need to call / run this anymore in future
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print(F("Hi There! First run"));
    lcd.setCursor(0, 1);
    lcd.print(F("Have written value's"));
    lcd.setCursor(0, 2);
    lcd.print(F("to EEPROM "));
    lcd.setCursor(0, 3);
    lcd.print(F("Thanks for trying"));
    for (int i = 30 ; i > 0 ; i--) {
      lcd.setCursor(17, 2);
      lcd.print(i);
      lcd.print(" ");
      delay(500);
    }
    lcd.clear();
  }


  // is written in eeprom like this
  // 665 255
  // 666 154       2x256+154=666
  // 667 2
  // 668 255
  /*
    0 30
    1 0
    2 240
    3 65
    4 255
    5 0
    6 0
    7 128
    8 178
    9 255
    10  154
    11  153
    12  153
    13  190
    14  255
    15  154
    16  153
    17  153
    18  62
    19  255
    20  88
    21  2
    22  255
    23  255
    24  255
    25  255
    26  255
    27  255
    28  255
    29  255
    30  90
    31  0
    32  255
    33  255
    34  255
    35  20
    36  0
    37  255
    38  255
    39  255
    40  255
  */




  // read stored valeus from eeprom
  EEPROM.get(0, SwitchOnTemp);
  EEPROM.get(5, CalibrationOffset);
  EEPROM.get(10, relayonpointbelowsetpoint);
  EEPROM.get(15, relayoffabovesetpoint);
  EEPROM.get(20, MaxTimeRelayMayBeonInSeconds);
  EEPROM.get(25, CoolorHeat);
  EEPROM.get(30, HighTempAlarmVal);
  EEPROM.get(35, LowTempAlarmVal);
  EEPROM.get(40, MaxTime2SetPoint);

  // A0 NTC thermistor
  //  pinMode(2, INPUT_PULLUP);       // set button
  //  pinMode(3, INPUT_PULLUP);       // + button
  //  pinMode(4, INPUT_PULLUP);       // - button

  //rotary encoder
  pinMode(CLK, INPUT);
  pinMode(CLK, INPUT_PULLUP);
  pinMode(DATA, INPUT);
  pinMode(DATA, INPUT_PULLUP);


  pinMode(10, OUTPUT);            // relais
  pinMode(11, OUTPUT);            // lowtemp alarm relais
  pinMode(12, OUTPUT);            // hightemp alarm relais
  pinMode(13, OUTPUT);            // another relais
}




void loop() {

  // int SetButton() = SetButton();
  // int PlusButton = PlusButton();
  // int MinButton = MinButton();

  if (!SetButton()) {                       //if !=not setbutton pressed
    menu = 1;
    while (SetButton() == LOW) {
      // loop until button released
      // maybe a timer here
      // alarm if button never released
      lcd.setCursor(0, 0);
      lcd.print(F("                    "));
      lcd.setCursor(0, 1);
      lcd.print(F(" In Menu System Now "));
      lcd.setCursor(0, 2);
      lcd.print(F("   Release Button   "));
      lcd.setCursor(0, 3);
      lcd.print(F("                    "));
    }
    lcd.clear();
  }



  //1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
  //setpoint setpoint setpoint setpoint setpoint setpoint setpoint setpoint setpoint setpoint setpoint setpoint setpoint setpoint
  TempLong = millis();  //reset innactive time counter
  if (menu == 1) {
    lcd.setCursor(0, 0);
    lcd.print(F("1 SetTemp"));
    lcd.setCursor(0, 1);
    lcd.print(SwitchOnTemp);
  }
  while (menu == 1) {
    if ((millis() - TempLong)  > 10000) {
      TimeOut();
      break;
    }

    float rval;
    if ( rval = read_rotary() ) {
      SwitchOnTemp = SwitchOnTemp + (rval / 10);
      TempLong = millis();  //reset innactive time counter
      lcd.setCursor(0, 1);
      lcd.print(SwitchOnTemp);
      lcd.print(F(" "));
      if (SwitchOnTemp > MaxTemp) SwitchOnTemp = MaxTemp;
      if (SwitchOnTemp < MinTemp) SwitchOnTemp = MinTemp;
    }

    if (!SetButton()) {                         //if !=not setbutton pressed
      menu = 2;
      lcd.clear();
      delay(250);
    }
  }


  EEPROM.get(0, TempFloat);                         // limmited write to eeprom = read is unlimmited
  if (SwitchOnTemp != TempFloat) {                  // only write to eeprom if value is different
    EEPROM.put(0, SwitchOnTemp);                    // put already checks if val is needed to write
    lcd.setCursor(0, 0);
    lcd.print(F("Saving to EEPROM"));
    lcd.setCursor(0, 2);
    lcd.print(TempFloat);
    lcd.print(F(" new= "));
    lcd.print(SwitchOnTemp);

    for (int i = 0; i < 100; i++)Serial.println(F("SwitchOnTemp DATA WRITEN / SAVED TO EEPROM "));
    lcd.clear();
  }






  //2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
  //calibration calibration calibration calibration calibration calibration calibration calibration calibration calibration calibration
  TempLong = millis();  //reset innactive time counter
  if (menu == 2) {
    lcd.setCursor(0, 0);
    lcd.print(F("2 Cal. Offset"));
    lcd.setCursor(0, 1);
    lcd.print(CalibrationOffset);
  }
  while (menu == 2) {
    if ((millis() - TempLong) > 10000) {
      TimeOut();
      break;
    }


    float rval;
    if ( rval = read_rotary() ) {
      CalibrationOffset = CalibrationOffset + (rval / 10);
      TempLong = millis();  //reset innactive time counter
      lcd.setCursor(0, 1);
      lcd.print(CalibrationOffset);
      lcd.print(F(" "));
      if (CalibrationOffset > 7)CalibrationOffset = 7;
      if (CalibrationOffset < -7)CalibrationOffset = -7;
    }

    if (!SetButton()) {                       //if !=not setbutton pressed
      menu = 3;
      lcd.clear();
      delay(250);
    }
  }

  EEPROM.get(5, TempFloat);                         // limmited write to eeprom = read is unlimmited
  if (CalibrationOffset != TempFloat) {             // only write to eeprom if value is different
    EEPROM.put(5, CalibrationOffset);               // i have no idea wat eeprom adress to use just jump to 5
    lcd.setCursor(0, 0);
    lcd.print(F("Saving to EEPROM"));
    lcd.setCursor(0, 2);
    lcd.print(TempFloat);
    lcd.print(F(" new= "));
    lcd.print(CalibrationOffset);
    for (int i = 0; i < 100; i++)Serial.println(F("CalibrationOffset DATA WRITEN / SAVED TO EEPROM "));
    lcd.clear();
  }

  //3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
  //below set below set below set below set below set below set below set below set below set below set below set below set below set
  TempLong = millis();  //reset innactive time counter
  if (menu == 3) {
    lcd.setCursor(0, 0);
    lcd.print(F("3 Below Set"));
    lcd.setCursor(0, 1);
    lcd.print(relayonpointbelowsetpoint);
  }
  while (menu == 3) {
    if ((millis() - TempLong) / 1000 > 20) {
      TimeOut();
      break;
    }

    float rval;
    if ( rval = read_rotary() ) {
      relayonpointbelowsetpoint  = relayonpointbelowsetpoint  + (rval / 10);
      TempLong = millis();  //reset innactive time counter
      lcd.setCursor(0, 1);
      lcd.print(relayonpointbelowsetpoint);
      lcd.print(F(" "));
      if (relayonpointbelowsetpoint > -0.1)relayonpointbelowsetpoint = -0.1;
      if (relayonpointbelowsetpoint < -2)relayonpointbelowsetpoint = -2;
    }

    if (!SetButton()) {                   //if !=not setbutton pressed
      menu = 4;
      lcd.clear();
      delay(250);
    }
  }

  EEPROM.get(10, TempFloat);                         // limmited write to eeprom = read is unlimmited
  if (relayonpointbelowsetpoint != TempFloat) {             // only write to eeprom if value is different
    EEPROM.put(10, relayonpointbelowsetpoint);               // i have no idea wat eeprom adress to use just jump to 10
    lcd.setCursor(0, 0);
    lcd.print(F("Saving to EEPROM"));
    lcd.setCursor(0, 2);
    lcd.print(TempFloat);
    lcd.print(F(" new= "));
    lcd.print(relayonpointbelowsetpoint);
    for (int i = 0; i < 100; i++)Serial.println(F("relayonpointbelowsetpoint DATA WRITEN / SAVED TO EEPROM "));
    lcd.clear();
  }


  //4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
  //above set above set above set above set above set above set above set above set above set above set above set above set
  TempLong = millis();  //reset innactive time counter
  if (menu == 4) {
    lcd.setCursor(0, 0);
    lcd.print(F("4 Above Set"));
    lcd.setCursor(0, 1);
    lcd.print(relayoffabovesetpoint);
  }
  while (menu == 4) {
    if ((millis() - TempLong) > 10000) {
      TimeOut();
      break;
    }

    float rval;
    if ( rval = read_rotary() ) {
      relayoffabovesetpoint  = relayoffabovesetpoint  + (rval / 10);
      TempLong = millis();  //reset innactive time counter
      lcd.setCursor(0, 1);
      lcd.print(relayoffabovesetpoint);
      lcd.print(F(" "));
      if (relayoffabovesetpoint > 2)relayoffabovesetpoint = 2;
      if (relayoffabovesetpoint < 0)relayoffabovesetpoint = 0;
    }

    if (!SetButton()) {              //if !=not setbutton pressed
      menu = 5;
      lcd.clear();
      delay(250);
    }
  }

  EEPROM.get(15, TempFloat);                         // limmited write to eeprom = read is unlimmited
  if (relayoffabovesetpoint != TempFloat) {             // only write to eeprom if value is different
    EEPROM.put(15, relayoffabovesetpoint);               // i have no idea wat eeprom adress to use just jump to 5
    lcd.setCursor(0, 0);
    lcd.print(F("Saving to EEPROM"));
    lcd.setCursor(0, 2);
    lcd.print(TempFloat);
    lcd.print(F(" new= "));
    lcd.print(relayoffabovesetpoint);
    for (int i = 0; i < 100; i++)Serial.println(F("relayoffabovesetpoint DATA WRITEN / SAVED TO EEPROM "));
    lcd.clear();
  }

  //5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
  //max t relay max t relay max t relay max t relay max t relay max t relay max t relay max t relay max t relay max t relay
  TempLong = millis();  //reset innactive time counter
  if (menu == 5) {
    lcd.setCursor(0, 0);
    lcd.print(F("5 Max T Relay on Sec"));
    lcd.setCursor(0, 1);
    lcd.print(MaxTimeRelayMayBeonInSeconds);
  }
  while (menu == 5) {
    if ((millis() - TempLong) > 10000) {
      TimeOut();
      break;
    }

    float rval;
    if ( rval = read_rotary() ) {
      MaxTimeRelayMayBeonInSeconds  = MaxTimeRelayMayBeonInSeconds  + rval;
      TempLong = millis();  //reset innactive time counter
      lcd.setCursor(0, 1);
      lcd.print(MaxTimeRelayMayBeonInSeconds);<wbr />
      lcd.print(F(" "));
      if (MaxTimeRelayMayBeonInSeconds < 30)MaxTimeRelayMayBeonInSeconds = 30;
      if (MaxTimeRelayMayBeonInSeconds > 3600)MaxTimeRelayMayBeonInSeconds = 3600;
    }

    if (!SetButton()) {                //if !=not setbutton pressed
      menu = 6;
      lcd.clear();
      delay(250);
    }
  }

  EEPROM.get(20, TempInt);                         // limmited write to eeprom = read is unlimmited
  if (MaxTimeRelayMayBeonInSeconds != TempInt) {             // only write to eeprom if value is different
    EEPROM.put(20, MaxTimeRelayMayBeonInSeconds);               // i have no idea wat eeprom adress to use just jump to 10
    lcd.setCursor(0, 0);
    lcd.print(F("Saving to EEPROM"));
    lcd.setCursor(0, 2);
    lcd.print(TempInt);
    lcd.print(F(" new= "));
    lcd.print(MaxTimeRelayMayBeonInSeconds);<wbr />
    for (int i = 0; i < 100; i++)Serial.println(F("MaxTimeRelayMayBeonInSeconds DATA WRITEN / SAVED TO EEPROM "));
    lcd.clear();
  }

  //6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6
  //CoolorHeat CoolorHeat CoolorHeat CoolorHeat CoolorHeat CoolorHeat
  TempLong = millis();  //reset innactive time counter
  if (menu == 6) {
    lcd.setCursor(0, 0);
    lcd.print(F("6 Cool / Heat"));
    lcd.setCursor(0, 1);
    if (CoolorHeat == 1)lcd.print(F("Not yet! = COOL"));
    if (CoolorHeat == 2)lcd.print(F("Not yet! = HEAT"));
  }
  while (menu == 6) {
    if ((millis() - TempLong) > 10000) {
      TimeOut();
      break;
    }

    float rval;
    if ( rval = read_rotary() ) {
      CoolorHeat  = CoolorHeat  + rval;
      TempLong = millis();  //reset innactive time counter
      lcd.setCursor(0, 1);
      lcd.print(CoolorHeat);
      lcd.print(F(" "));
      if (CoolorHeat < 1)CoolorHeat = 2;
      if (CoolorHeat > 2)CoolorHeat = 1;
      lcd.setCursor(0, 1);
      if (CoolorHeat == 1)lcd.print(F("Not yet! = COOL"));
      if (CoolorHeat == 2)lcd.print(F("Not yet! = HEAT"));
    }

    if (!SetButton()) { //if !=not setbutton pressed
      menu = 7;
      lcd.clear();
      delay(250);
    }
  }

  EEPROM.get(25, TempByte);                         // limmited write to eeprom = read is unlimmited
  if (CoolorHeat != TempByte) {                     // only write to eeprom if value is different
    EEPROM.put(25, CoolorHeat);                     // i have no idea wat eeprom adress to use just jump to 10
    lcd.setCursor(0, 0);
    lcd.print(F("Saving to EEPROM"));
    lcd.setCursor(0, 2);
    lcd.print(TempByte);
    lcd.print(F(" new= "));
    if (CoolorHeat == 1)lcd.print(F("COOL"));
    if (CoolorHeat == 2)lcd.print(F("HEAT"));
    for (int i = 0; i < 100; i++)Serial.println(F("Cool/Heat DATA WRITEN / SAVED TO EEPROM "));
    lcd.clear();
  }







  //777777777777777777777777777777777777777777777777777777777777777777777
  TempLong = millis();  //reset innactive time counter
  if (menu == 7) {
    lcd.setCursor(0, 0);
    lcd.print(F("7 High Temp Alarm"));
    lcd.setCursor(0, 1);
    lcd.print(HighTempAlarmVal );
  }
  while (menu == 7) {
    if ((millis() - TempLong) > 10000) {
      TimeOut();
      break;
    }

    float rval;
    if ( rval = read_rotary() ) {
      HighTempAlarmVal  = HighTempAlarmVal  + rval;
      TempLong = millis();  //reset innactive time counter
      lcd.setCursor(0, 1);
      lcd.print(HighTempAlarmVal );
      lcd.print(F(" "));
      if (HighTempAlarmVal > MaxTemp)HighTempAlarmVal = MaxTemp;
      if (HighTempAlarmVal < MinTemp)HighTempAlarmVal = MinTemp;
    }

    if (!SetButton()) {                     //if !=not setbutton pressed
      menu = 8;
      lcd.clear();
      delay(250);
    }
  }

  EEPROM.get(30, TempInt);                         // limmited write to eeprom = read is unlimmited
  if (HighTempAlarmVal != TempInt) {             // only write to eeprom if value is different
    EEPROM.put(30, HighTempAlarmVal);               // i have no idea wat eeprom adress to use just jump to 10
    lcd.setCursor(0, 0);
    lcd.print(F("Saving to EEPROM"));
    lcd.setCursor(0, 2);
    lcd.print(TempInt);
    lcd.print(F(" new= "));
    lcd.print(HighTempAlarmVal);
    for (int i = 0; i < 100; i++)Serial.println(F("HighTempAlarmVal DATA WRITEN / SAVED TO EEPROM "));
    lcd.clear();
  }

  //888888888888888888888888888888888888888888888888888888888888888888888888888888
  TempLong = millis();  //reset innactive time counter
  if (menu == 8) {
    lcd.setCursor(0, 0);
    lcd.print(F("8 Low Temp Alarm"));
    lcd.setCursor(0, 1);
    lcd.print(LowTempAlarmVal );
    lcd.print(F(" "));
  }
  while (menu == 8) {
    if ((millis() - TempLong) > 10000) {
      TimeOut();
      break;
    }

    float rval;
    if ( rval = read_rotary() ) {
      LowTempAlarmVal  = LowTempAlarmVal  + rval;
      TempLong = millis();  //reset innactive time counter
      lcd.setCursor(0, 1);
      lcd.print(LowTempAlarmVal );
      lcd.print(F(" "));
      if (LowTempAlarmVal > MaxTemp)LowTempAlarmVal = MaxTemp;
      if (LowTempAlarmVal < MinTemp)LowTempAlarmVal = MinTemp;
    }

    if (!SetButton()) {
      menu = 9;
      lcd.clear();
      delay(250);
    }
  }


  EEPROM.get(35, TempInt);                         // limmited write to eeprom = read is unlimmited
  if (LowTempAlarmVal != TempInt) {             // only write to eeprom if value is different
    EEPROM.put(35, LowTempAlarmVal);               // i have no idea wat eeprom adress to use just jump to 10
    lcd.setCursor(0, 0);
    lcd.print(F("Saving to EEPROM"));
    lcd.setCursor(0, 2);
    lcd.print(TempInt);
    lcd.print(F(" new= "));
    lcd.print(LowTempAlarmVal);
    for (int i = 0; i < 100; i++)Serial.println(F("LowTempAlarmVal DATA WRITEN / SAVED TO EEPROM "));
    lcd.clear();
  }




  //9999999999999999999999999999999999999999999999999999999999999999999999999999999999999
  TempLong = millis();  //reset innactive time counter
  if (menu == 9) {
    lcd.setCursor(0, 0);
    lcd.print(F("9 MaxTime2SetPoint"));
    lcd.setCursor(0, 1);
    lcd.print(MaxTime2SetPoint );
    lcd.print(F(" "));
  }
  while (menu == 9) {
    if ((millis() - TempLong) > 10000) {
      TimeOut();
      break;
    }

    float rval;
    if ( rval = read_rotary() ) {
      MaxTime2SetPoint  = MaxTime2SetPoint  + rval;
      TempLong = millis();  //reset innactive time counter
      lcd.setCursor(0, 1);
      lcd.print(MaxTime2SetPoint );
      lcd.print(F(" "));
      if (MaxTime2SetPoint > MaxTimeRelayMayBeonInSeconds)MaxTime2Set<wbr />Point = MaxTimeRelayMayBeonInSeconds;
      if (MaxTime2SetPoint < 0)MaxTime2SetPoint = 0;
    }

    if (!SetButton()) {
      menu = 10;
      lcd.clear();
      delay(250);
    }
  }


  EEPROM.get(40, TempInt);                         // limmited write to eeprom = read is unlimmited
  if (MaxTime2SetPoint != TempInt) {             // only write to eeprom if value is different
    EEPROM.put(40, MaxTime2SetPoint);               // i have no idea wat eeprom adress to use just jump to 10
    lcd.setCursor(0, 0);
    lcd.print(F("Saving to EEPROM"));
    lcd.setCursor(0, 2);
    lcd.print(TempInt);
    lcd.print(F(" new= "));
    lcd.print(MaxTime2SetPoint);
    for (int i = 0; i < 100; i++)Serial.println(F("MaxTime2SetPoint DATA WRITEN / SAVED TO EEPROM "));
    lcd.clear();
  }





  //10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10
  TempLong = millis();  //reset innactive time counter
  yesorno = 2;
  if (menu == 10) {
    lcd.setCursor(0, 0);
    lcd.print(F("10 Factory Reset"));
    lcd.setCursor(8, 2);
    if (yesorno == 1)lcd.print(F("YES"));
    if (yesorno == 2)lcd.print(F("NO "));
  }
  while (menu == 10) {
    if ((millis() - TempLong) > 10000) {
      TimeOut();
      break;
    }

    float rval;
    if ( rval = read_rotary() ) {
      yesorno  = yesorno  + rval;
      TempLong = millis();  //reset innactive time counter
      if (yesorno < 1)yesorno = 2;
      if (yesorno > 2)yesorno = 1;
      lcd.setCursor(8, 2);
      if (yesorno == 1)lcd.print(F("YES"));
      if (yesorno == 2)lcd.print(F("NO "));
    }


    if (!SetButton() && yesorno == 1) {
      EEPROM.put(0, 30.00);         // setpoint
      EEPROM.put(5, 0.00);          // callibration offset
      EEPROM.put(10, -0.3);         // below on
      EEPROM.put(15, 0.3);          // above off
      EEPROM.put(20, 600);          // max time in seconds relay on
      EEPROM.put(25, 2);            // 1=cool 2=heat
      EEPROM.put(30, 90);           // high temp alarm
      EEPROM.put(35, 20);           // low temp alarm
      EEPROM.put(40, 300);
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print(F("Saving to EEPROM"));
      for (int i = 0; i < 100; i++)Serial.println(F(" valeus restored to factory settings "));
      // read stored valeus from eeprom
      EEPROM.get(0, SwitchOnTemp);
      EEPROM.get(5, CalibrationOffset);
      EEPROM.get(10, relayonpointbelowsetpoint);
      EEPROM.get(15, relayoffabovesetpoint);
      EEPROM.get(20, MaxTimeRelayMayBeonInSeconds);
      EEPROM.get(25, CoolorHeat);
      EEPROM.get(30, HighTempAlarmVal);
      EEPROM.get(35, LowTempAlarmVal);
      EEPROM.get(40, MaxTime2SetPoint);
      delay(1000);
      menu = 11;
      lcd.clear();

    }

    if (!SetButton() && yesorno == 2) { //no + button
      menu = 11;
      lcd.clear();
      delay(250);
    }

  }





  //11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11
  TempLong = millis();  //reset innactive time counter
  while (menu == 11) {
    if ((millis() - TempLong) / 1000 > 20) {
      TimeOut();
      break;
    }
    //runtime since boot/start days hours minutes seconds
    Serial.println(F(" rumtime menu"));
    lcd.setCursor(0, 0);
    lcd.print(F("10 RunTime"));
    lcd.setCursor(3, 2);
    lcd.print((millis() / 86400000) % 365);
    lcd.print(" ");
    lcd.print((millis() / 3600000) % 24);
    lcd.print(":");
    lcd.print((millis() / 60000) % 60);
    lcd.print(":");
    lcd.print((millis() / 1000) % 60);
    lcd.print("  ");


    if (SetButton() == LOW) {
      menu = 0;
      lcd.clear();
      delay(250);
    }

  }





  Read_NTC_Thermistor();

  //Vo = analogRead(ThermistorPin);
  R2 = R1 * (1023.0 / (float)Vo - 1.0);
  logR2 = log(R2);
  T = (1.0 / (c1 + c2 * logR2 + c3 * logR2 * logR2 * logR2));
  Tc = T - 273.15 + CalibrationOffset;

  //Tf = (Tc * 9.0)/ 5.0 + 32.0; // fahrenheit



  // compare actualtemp to switchpoint with offsets

  if (Tc < SwitchOnTemp + relayonpointbelowsetpoint) {
    RelaisState = 1;
  }
  if (Tc > SwitchOnTemp + relayoffabovesetpoint) {
    RelaisState = 0;
  }


  if (Tc < LowTempAlarmVal) {
    for (int i = 0; i < 10; i++)Serial.println(F(" Alarm Temperature LOW "));
    lcd.setCursor(2, 2);
    lcd.print(F("Alarm Temp. LOW"));

    digitalWrite(11, 1);
  } else {
    digitalWrite(11, 0);

  }

  if (Tc > HighTempAlarmVal) {
    for (int i = 0; i < 10; i++)Serial.println(F(" Alarm Temperature HIGH "));
    digitalWrite(12, 1);
    lcd.setCursor(2, 2);
    lcd.print(F("Alarm Temp. High"));

  } else {
    digitalWrite(12, 0);
  }




  Serial.print(F("D10 "));
  Serial.print(RelaisState);

  Serial.print(F(" A0 "));
  Serial.print(Vo);
  Serial.print(F(" Temp "));
  Serial.print(Tc, 1);  // 1 decimal

  lcd.setCursor(2, 1);
  lcd.print(Tc, 1);
  lcd.print("\337C");//Cdegree sign


  if (Vo <= 60) {
    for (int i = 0; i < 10; i++)Serial.println(F(" analogread < 60 ERROR LOW "));
    RelaisState = 0; //turn off relays
    lcd.setCursor(2, 2);
    lcd.print(F("Alarm sensor low?"));
  }
  if (Vo >= 960) {
    for (int i = 0; i < 10; i++)Serial.println(F(" analogread > 960 ERROR HIGH "));
    RelaisState = 0; //turn off relays
    lcd.setCursor(2, 2);
    lcd.print(F("Alarm sensor high?"));

  }



  //Serial.print("menu nr ");
  //Serial.print(menu);

  Serial.print(F(" Set "));
  Serial.print(SwitchOnTemp);
  lcd.setCursor(10, 1);
  lcd.print(SwitchOnTemp, 1);
  lcd.print("\337C");   //Cdegree sign


  //Serial.print(" TempFloat ");
  //Serial.print(TempFloat);
  //Serial.print(" TempInt ");
  //Serial.print(TempInt);
  //Serial.print(" TempLong ");
  //Serial.print(TempLong);

  Serial.print(F(" Below "));
  Serial.print(relayonpointbelowsetpoint);<wbr />
  Serial.print(F(" Above "));
  Serial.print(relayoffabovesetpoint);

<wbr />
  Serial.print(F(" Offset "));
  Serial.print(CalibrationOffset);

  Serial.print(F(" Lalarm "));
  Serial.print(LowTempAlarmVal);
  Serial.print(F(" Halarm "));
  Serial.print(HighTempAlarmVal);

  if (RelaisState == 0) {
    digitalWrite(10, 0);
    starttime = millis();
  }
  if (RelaisState == 1 && digitalRead(10) == 0) {
    digitalWrite(10, 1);
    starttime = millis();
  }

  timeon =  (millis() - starttime) / 1000;
  Serial.print(F(" MaxT "));
  Serial.print(MaxTimeRelayMayBeonInSecond<wbr />s);

  Serial.print(F(" Ton "));
  Serial.print(timeon);

  if (RelaisState == 1 ) {
    lcd.setCursor(0, 4);
    lcd.print(timeon);
    lcd.print(F(" Sec. Relay ON "));
  } else {
    lcd.setCursor(0, 4);
    lcd.print(F("Relay OFF        "));
  }

  EEPROM.get(666, TempInt);
  Serial.print(F(" Devil "));
  Serial.println(TempInt);


  if (timeon > MaxTimeRelayMayBeonInSeconds) {            //if there is a sensor fail or heating fail
    for (int i = 0; i < 10; i++)Serial.println(F(" >>>>>>>> ERROR max time relay ON <<<<<<<<<"));
    //shutdown more??? relay should not be on so long
    lcd.setCursor(1, 2);
    lcd.print(F("Max Time Relay ON"));
    delay(1000);
    lcd.setCursor(1, 2);
    lcd.print(F("                 "));
  }

  if (timeon > MaxTime2SetPoint) {            //
    for (int i = 0; i < 10; i++)Serial.println(F(" >>>>>>>> time on 2 desired setpoint to long <<<<<<<<<"));
    //shutdown more??? relay should not be on so long
    lcd.setCursor(1, 2);
    lcd.print(F("Warning heat time >"));
    delay(1000);
    lcd.setCursor(1, 2);
    lcd.print(F("                   "));

  }



  //delay(50);

  // if you change the program to make it do more or better
  // would like to know/share
  // https://m.facebook.com/luberth.dijkman
  // http://84.106.2.21:8888/forum/index.php?<wbr />action=view&id=296

}
//end loop







//maybe above code is better to read if i do button digitalread like this
boolean SetButton() {
  boolean sval;
  sval = digitalRead(2);
  //Serial.print(F("SetButton="));
  //Serial.println(sval);
  return sval;
}

boolean PlusButton() {
  boolean sval;
  sval = digitalRead(3);
  Serial.print(F("PlusButton="));
  Serial.println(sval);
  return sval;
}

boolean MinButton() {
  boolean sval;
  sval = digitalRead(4);
  Serial.print(F("MinButton="));
  Serial.println(sval);
  return sval;
}

int Read_NTC_Thermistor() {
  for (int i = 0; i < 500; i++) {
    Vo = Vo + analogRead(A0);             // found temp value displayed bouncy noisy fluctuating
    delay(1);                             // do 500 analog ntc readings and divide by 200 to get an average
  }
  Vo = Vo / 500;
  return Vo;
}


void TimeOut() {
  lcd.clear();  //exit menu if 20 seconds innactive
  lcd.setCursor(0, 1);
  lcd.print(F("TimeOut"));
  lcd.setCursor(0, 2);
  lcd.print(F("Return to Mainscreen"));
  delay(2000);
  lcd.clear();
  menu = 0;
}





int8_t read_rotary() {
  static int8_t rot_enc_table[] = {0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0};
  
  // Robust Rotary encoder reading
  // Copyright John Main - best-microcontroller-projects.com
  // https://www.best-microcontroller-projects.com/rotary-encoder.html

  prevNextCode <<= 2;
  if (digitalRead(DATA)) prevNextCode |= 0x02;
  if (digitalRead(CLK)) prevNextCode |= 0x01;
  prevNextCode &= 0x0f;

  // If valid then store as 16 bit data.
  if  (rot_enc_table[prevNextCode] ) {
    store <<= 4;
    store |= prevNextCode;
    //if (store==0xd42b) return 1;
    //if (store==0xe817) return -1;
    if ((store & 0xff) == 0x2b) return -1;
    if ((store & 0xff) == 0x17) return 1;
  }
  return 0;
  
  // Robust Rotary encoder reading
  // Copyright John Main - best-microcontroller-projects.com
  // https://www.best-microcontroller-projects.com/rotary-encoder.html
}



// it is mostly air i live on
// but i could use your support
// a nickle or dime for every device you put this code on
// would be appreciated http://paypal.me/pools/c/8amUN5rgb9
// more is allowed










ThumbNail size tiny 2euro i2c oled display test

ThumbNail size tiny 2euro i2c oled display test




//cannot (F("strings")) with <U8x8lib.h> //Using u8g2 library 
// solution???
// u8x8.setCursor(32, 32);
// u8x8.print(F("Hello."));
// (F("")); strings saves runmemory

//https://github.com/olikra<wbr />us/u8g2/wiki/fntlist8x8


#include <Arduino.h>
#include <U8x8lib.h>     //Using u8g2 librarymanager search u8g2

//U8X8_SSD1306_128X64_NONAME_SW_<wbr />I2C u8x8(12, 11, U8X8_PIN_NONE);
U8X8_SSD1306_128X64_NON<wbr />AME_HW_I2C u8x8(U8X8_PIN_NONE);

void setup(void)
{
  u8x8.begin();
  u8x8.setPowerSave(0);
}

void loop(void)
{ 
  u8x8.setFont(u8x8_font_pxplusibmcgathin_<wbr />f);//https://github.com/olikraus/u8g2/wi<wbr />ki/fntlist8x8
  u8x8.setCursor(0, 2);
  u8x8.print(F("Luberth Dijkman"));
  delay(2000);
  
  u8x8.clear();
  u8x8.setFont(u8x8_font_pxplusibmcgathin_<wbr />f);//https://github.com/olikraus/u8g2/wi<wbr />ki/fntlist8x8
  u8x8.drawString(0, 0, "1 128x64 oled   ");
  u8x8.drawString(0, 1, "8 lines 16 char ");
  u8x8.drawString(0, 2, "need glasses    ");
  u8x8.drawString(0, 3, "small display   ");
  u8x8.drawString(0, 4, "cheap display   ");
  u8x8.drawString(0, 5, "this is line 6  ");
  u8x8.drawString(0, 6, "this  is line  7");
  u8x8.drawString(0, 7, "and this line  8");
  delay(2000);
  
  u8x8.clear();
  u8x8.setFont(u8x8_font_chroma48medium8_r<wbr />);//https://github.com/olikraus/u8g2/wik<wbr />i/fntlist8x8
  u8x8.drawString(0, 0, "u8x8 OLED Demo");
  delay(2000);
  
  u8x8.clear();
  u8x8.setFont(u8x8_font_amstrad_cpc_exten<wbr />ded_r);//https://github.com/olikraus/u8g<wbr />2/wiki/fntlist8x8
  u8x8.drawString(0, 0, "Hello World");
  delay(2000);
  
  u8x8.clear();
  u8x8.setFont(u8x8_font_5x7_f);//https://<wbr />github.com/olikraus/u8g2/wiki/fntlist8x8<wbr />
  u8x8.drawString(0, 0, "1 128x64 oled   ");
  u8x8.drawString(0, 1, "8 lines 16 char ");
  u8x8.drawString(0, 2, "need glasses    ");
  u8x8.drawString(0, 3, "small display   ");
  u8x8.drawString(0, 4, "cheap display   ");
  u8x8.drawString(0, 5, "this is line 6  ");
  u8x8.drawString(0, 6, "this  is line  7");
  u8x8.drawString(0, 7, "and this line  8");
  delay(5000);
  
  u8x8.clear();
  u8x8.setFont(u8x8_font_px437wyse700b_2x2<wbr />_r);  // Version 2.25.x//https://github.com/olikraus/u8g2<wbr />/wiki/fntlist8x8
  u8x8.drawString(0, 0, "Line 123");
  u8x8.drawString(0, 2, "LINE 2");
  u8x8.drawString(0, 4, "Line 3");
  u8x8.drawString(0, 6, "LINE 4");
  delay(5000);
  u8x8.clear();
 
  u8x8.clear();
  u8x8.setFont(u8x8_font_inb21_2x4_n);  // Version 2.25.x//https://github.com/olikraus/u8g2<wbr />/wiki/fntlist8x8
  u8x8.drawString(0, 0, "12345678");
  u8x8.drawString(0, 4, "12345678");
  delay(5000);
  u8x8.clear();

  u8x8.clear();
  u8x8.setFont(u8x8_font_inb33_3x6_n);  // Version 2.25.x//https://github.com/olikraus/u8g2<wbr />/wiki/fntlist8x8
  u8x8.drawString(0, 0, "12345");
  delay(5000);
  u8x8.clear();

  u8x8.clear();
  u8x8.setFont(u8x8_font_inb46_4x8_n);  // Version 2.25.x//https://github.com/olikraus/u8g2<wbr />/wiki/fntlist8x8
  u8x8.drawString(0, 0, "1234");
  delay(5000);
  u8x8.clear();


  
}






for those who are young and have good eyes
2 euro arduino nano 2
2 euro i2c oled display 128x64
50 cent ntc thermistor
1 euro rotary encoder pushbutton
4 euro relais print

50 cent passive buzzer module on D8
passive you have to create a tone by on/off switching PWM
tone(8,1000); //output D8 1000Hz
delay(1000);
noTone(8);
active buzzer module only needs power => no fun cannot change sound it i think





//version 27 june 2019 
// should become a safe arduino version of w1209 thermostat
//
// but far from finished
// i think in this rotary encoder i2c oled 128x64 version all is working now
// should become a safe arduino version of w1209 thermostat
// but far from finished
// parts of code used from
// http://www.circuitbasics.com/arduino-the<wbr />rmistor-temperature-sensor-tutorial/
// https://github.com/tehniq3/DS18B20_therm<wbr />ostat_4digit_7segment_led_display/blob/m<wbr />aster/4dig7segm_ac_18b20_thermostat_ver4<wbr />m7.ino
// Robust Rotary encoder reading
// Copyright John Main - best-microcontroller-projects.com
// https://www.best-microcontroller-project<wbr />s.com/rotary-encoder.html
//
// this code came from
// http://84.106.2.21:8888/forum/index.php?<wbr />action=view&id=296
// copyright then, now, and forever, luberth dijkman bangert 30 andijk the netherlands
// bob-a-job
// a nickle or dime would be apreciated http://paypal.me/pools/c/8amUN5rgb9
// if you gave me 5 cents for every device you program with this code
// i will be verry happy
// it doesnt hurt
// http://paypal.me/pools/c/8amUN5rgb9
//
// I Feel so lonely in this Universe ;-(
// if you change the program to make it do more or better
// would like to know/share
// https://m.facebook.com/luberth.dijkman
<wbr />// http://84.106.2.21:8888/forum/index.php?<wbr />action=view&id=296


#include <EEPROM.h>
//#include <LiquidCrystal_I2C.h>                     // https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/Home
//LiquidCrystal_I2C  lcd(0x27, 2, 1, 0, 4, 5, 6, 7);
#include <Arduino.h>
#include <U8x8lib.h>     //Using u8g2 library => search librarymanager for u8g2 and install
#include "pitches.h"     //https://www.arduino.cc/en/Tutorial/ton<wbr />eMelody


// die zien we nooit meer terug cocktail trio vlooiencircus 1965 https://www.youtube.com/watch?v=DizwZ0uO<wbr />X5A
// notes in the melody:  //from #include "pitches.h"
int melody[] = {
  NOTE_C4, NOTE_G3, NOTE_G3, NOTE_A3, NOTE_G3, 0, NOTE_B3, NOTE_C4
};

// note durations: 4 = quarter note, 8 = eighth note, etc.:
int noteDurations[] = {
  4, 8, 8, 4, 4, 4, 4, 4
};


//U8X8_SSD1306_128X64_NONAME_<wbr />SW_I2C u8x8(12, 11, U8X8_PIN_NONE);
U8X8_SSD1306_128X64_NON<wbr />AME_HW_I2C u8x8(U8X8_PIN_NONE);
float Vo;
float R1 = 10000;
float logR2, R2, T, Tc, Tf;
float c1 = 1.009249522e-03, c2 = 2.378405444e-04, c3 = 2.019202697e-07;
float CalibrationOffset = 0; //w1209 thermostat has -7 to +7 0.1 steps

float SwitchOnTemp = 30.0f;
byte TempByte;
float TempFloat;
int TempInt;
unsigned long TempLong;
byte val;
int RelaisState = 0;
byte CoolorHeat = 2; //1=cool 2=heat

int delayval;
float MaxTemp = 110;
float MinTemp = -40;
int LowTempAlarmVal = 0 ;
int HighTempAlarmVal = 100;

float relayonpointbelowsetpoint = -0.2;
float relayoffabovesetpoint = 0.1;

int menu = 0;
unsigned long starttime;
unsigned long timeon;

int MaxTimeRelayMayBeonInSeconds = 600;
int MaxTime2SetPoint = 300;

// Robust Rotary encoder reading
// Copyright John Main - best-microcontroller-projects.com
#defi<wbr />ne CLK 3
#define DATA 4
static uint8_t prevNextCode = 0;
static uint16_t store = 0;

int yesorno; //factory reset




void setup() {

  //Serial.begin(115200);
  Serial.begin(9600);

  //u8x8.begin(20, 4);
  // u8x8.setBacklightPin(3, POSITIVE);
  // u8x8.setBacklight(HIGH);
  u8x8.begin();
  u8x8.setPowerSave(0);
  u8x8.setFont(u8x8_font_pxplusibmcgathin_<wbr />f);

  // first time i use eeprom, thought it would be very hard to use
  // i make steps of 5 in eeprom adres because i did not know what to use
  // 5 is a nice step when i look with the eeprom read example from arduino
  // not optimal use of eeprom but have eeprom more then i use

  /*
    // next is for test => normally commented
    // erase eeprom all to 0
        for (int i = 0 ; i < EEPROM.length() ; i++){EEPROM.put(i, 0);
                            //was eeprom.write but i think put is better   put only writes when val not the same
            u8x8.setCursor(2, 1);u8x8.print(i);u8x8.print(" Erase EEPROM");
        } // erase eeprom all to 0
       for (int i = 30 ; i > 0 ; i--){u8x8.setCursor(9, 3);u8x8.print(i);u8x8.print(" ");delay(500);}
    // erase eeprom all to 0
  */


  // first run ??? write some val to eeprom if value at eepromadres 666 not is 666
  //if this is first run then val will not be 666 at eeprom adres 666 so next will be run
  EEPROM.get(666, TempInt);
  if (TempInt != 666) {           // IF this is the first run THEN val at eeprom adres 666 is -1???
    EEPROM.put(0, 31.00);         // setpoint
    EEPROM.put(5, 0.00);          // callibration offset
    EEPROM.put(10, -0.3);         // below on
    EEPROM.put(15, 0.3);          // above off
    EEPROM.put(20, 600);          // max time in seconds relay on
    EEPROM.put(25, 2);            // 1 cool 2 heat
    EEPROM.put(30, 90);           // high temp alarm
    EEPROM.put(35, 20);           // low temp alarm
    EEPROM.put(40, 300);
    EEPROM.put(666, 666);        // set eepromadres 666 to val 666 no need to call / run this anymore in future
    u8x8.clear();
    u8x8.setCursor(0, 0);
    u8x8.print(F("Hi There! First run"));
    u8x8.setCursor(0, 1);
    u8x8.print(F("Have written value's"));
    u8x8.setCursor(0, 2);
    u8x8.print(F("to EEPROM "));
    u8x8.setCursor(0, 3);
    u8x8.print(F("Thanks for trying"));
    for (int i = 30 ; i > 0 ; i--) {
      u8x8.setCursor(17, 2);
      u8x8.print(i);
      u8x8.print(" ");
      delay(500);
    }
    u8x8.clear();
  }


  // is written in eeprom like this
  // 665 255
  // 666 154       2x256+154=666
  // 667 2
  // 668 255
  /*
    0 30
    1 0
    2 240
    3 65
    4 255
    5 0
    6 0
    7 128
    8 178
    9 255
    10  154
    11  153
    12  153
    13  190
    14  255
    15  154
    16  153
    17  153
    18  62
    19  255
    20  88
    21  2
    22  255
    23  255
    24  255
    25  255
    26  255
    27  255
    28  255
    29  255
    30  90
    31  0
    32  255
    33  255
    34  255
    35  20
    36  0
    37  255
    38  255
    39  255
    40  255
  */




  // read stored valeus from eeprom
  EEPROM.get(0, SwitchOnTemp);
  EEPROM.get(5, CalibrationOffset);
  EEPROM.get(10, relayonpointbelowsetpoint);
  EEPROM.get(15, relayoffabovesetpoint);
  EEPROM.get(20, MaxTimeRelayMayBeonInSeconds);
  EEPROM.get(25, CoolorHeat);
  EEPROM.get(30, HighTempAlarmVal);
  EEPROM.get(35, LowTempAlarmVal);
  EEPROM.get(40, MaxTime2SetPoint);

  // A0 NTC thermistor
  //  pinMode(2, INPUT_PULLUP);       // set button
  //  pinMode(3, INPUT_PULLUP);       // + button
  //  pinMode(4, INPUT_PULLUP);       // - button

  //rotary encoder
  pinMode(2, INPUT_PULLUP);         // D2 rotary encoder button
  pinMode(CLK, INPUT);              // D3
  pinMode(CLK, INPUT_PULLUP);
  pinMode(DATA, INPUT);             // D4
  pinMode(DATA, INPUT_PULLUP);

  pinMode (8, OUTPUT);            // D8 passive buzzer module
  pinMode(10, OUTPUT);            // relais
  pinMode(11, OUTPUT);            // lowtemp alarm relais
  pinMode(12, OUTPUT);            // hightemp alarm relais
  pinMode(13, OUTPUT);            // another relais
}




void loop() {

  // int SetButton() = SetButton();
  // int PlusButton = PlusButton();
  // int MinButton = MinButton();

  if (!SetButton()) {                       //if !=not setbutton pressed
    menu = 1;
    while (SetButton() == LOW) {
      // loop until button released
      // maybe a timer here
      // alarm if button never released
      u8x8.setCursor(0, 0);
      u8x8.print(F("                "));
      u8x8.setCursor(0, 1);
      u8x8.print(F("  In Menu Now   "));
      u8x8.setCursor(0, 2);
      u8x8.print(F(" Release Button "));
      u8x8.setCursor(0, 3);
      u8x8.print(F("                "));
      u8x8.setCursor(0, 4);
      u8x8.print(F("                "));
    }
    u8x8.clear();
  }






  //1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
  //setpoint setpoint setpoint setpoint setpoint setpoint setpoint setpoint setpoint setpoint setpoint setpoint setpoint setpoint
  TempLong = millis();  //reset innactive time counter
  if (menu == 1) {
    u8x8.setCursor(0, 0);
    u8x8.print(F("1 SetTemp"));
    u8x8.setCursor(0, 1);
    u8x8.print(SwitchOnTemp);
  }
  while (menu == 1) {
    if ((millis() - TempLong)  > 10000) {
      TimeOut();
      break;
    }

    float rval;
    if ( rval = read_rotary() ) {
      SwitchOnTemp = SwitchOnTemp + (rval / 10);
      TempLong = millis();  //reset innactive time counter
      u8x8.setCursor(0, 1);
      u8x8.print(SwitchOnTemp);
      u8x8.print(F(" "));
      if (SwitchOnTemp > MaxTemp) SwitchOnTemp = MaxTemp;
      if (SwitchOnTemp < MinTemp) SwitchOnTemp = MinTemp;
    }

    if (!SetButton()) {                         //if !=not setbutton pressed
      while (SetButton() == LOW); // wait for release button do not fly trough all the menus
      menu = 2;
      u8x8.clear();
      delay(250);
    }
  }


  EEPROM.get(0, TempFloat);                         // limmited write to eeprom = read is unlimmited
  if (SwitchOnTemp != TempFloat) {                  // only write to eeprom if value is different
    EEPROM.put(0, SwitchOnTemp);                    // put already checks if val is needed to write
    u8x8.setCursor(0, 0);
    u8x8.print(F("Saving to EEPROM"));
    u8x8.setCursor(0, 2);
    u8x8.print(TempFloat);
    u8x8.print(F(" new= "));
    u8x8.print(SwitchOnTemp);

    for (int i = 0; i < 100; i++)Serial.println(F("SwitchOnTemp DATA WRITEN / SAVED TO EEPROM "));
    u8x8.clear();
  }






  //2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
  //calibration calibration calibration calibration calibration calibration calibration calibration calibration calibration calibration
  TempLong = millis();  //reset innactive time counter
  if (menu == 2) {
    u8x8.setCursor(0, 0);
    u8x8.print(F("2 Cal. Offset"));
    u8x8.setCursor(0, 1);
    u8x8.print(CalibrationOffset);
  }
  while (menu == 2) {
    if ((millis() - TempLong) > 10000) {
      TimeOut();
      break;
    }


    float rval;
    if ( rval = read_rotary() ) {
      CalibrationOffset = CalibrationOffset + (rval / 10);
      TempLong = millis();  //reset innactive time counter
      u8x8.setCursor(0, 1);
      u8x8.print(CalibrationOffset);
      u8x8.print(F(" "));
      if (CalibrationOffset > 7)CalibrationOffset = 7;
      if (CalibrationOffset < -7)CalibrationOffset = -7;
    }

    if (!SetButton()) {                       //if !=not setbutton pressed
      while (SetButton() == LOW); // wait for release button do not fly trough all the menus
      menu = 3;
      u8x8.clear();
      delay(250);
    }
  }

  EEPROM.get(5, TempFloat);                         // limmited write to eeprom = read is unlimmited
  if (CalibrationOffset != TempFloat) {             // only write to eeprom if value is different
    EEPROM.put(5, CalibrationOffset);               // i have no idea wat eeprom adress to use just jump to 5
    u8x8.setCursor(0, 0);
    u8x8.print(F("Saving to EEPROM"));
    u8x8.setCursor(0, 2);
    u8x8.print(TempFloat);
    u8x8.print(F(" new= "));
    u8x8.print(CalibrationOffset);
    for (int i = 0; i < 100; i++)Serial.println(F("CalibrationOffset DATA WRITEN / SAVED TO EEPROM "));
    u8x8.clear();
  }







  //3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
  //below set below set below set below set below set below set below set below set below set below set below set below set below set
  TempLong = millis();  //reset innactive time counter
  if (menu == 3) {
    u8x8.setCursor(0, 0);
    u8x8.print(F("3 Below Set"));
    u8x8.setCursor(0, 1);
    u8x8.print(relayonpointbelowsetpoint);
  }
  while (menu == 3) {
    if ((millis() - TempLong) / 1000 > 20) {
      TimeOut();
      break;
    }

    float rval;
    if ( rval = read_rotary() ) {
      relayonpointbelowsetpoint  = relayonpointbelowsetpoint  + (rval / 10);
      TempLong = millis();  //reset innactive time counter
      u8x8.setCursor(0, 1);
      u8x8.print(relayonpointbelowsetpoint);
      u8x8.print(F(" "));
      if (relayonpointbelowsetpoint > -0.1)relayonpointbelowsetpoint = -0.1;
      if (relayonpointbelowsetpoint < -2)relayonpointbelowsetpoint = -2;
    }

    if (!SetButton()) {                   //if !=not setbutton pressed
      while (SetButton() == LOW); // wait for release button do not fly trough all the menus
      menu = 4;
      u8x8.clear();
      delay(250);
    }
  }

  EEPROM.get(10, TempFloat);                         // limmited write to eeprom = read is unlimmited
  if (relayonpointbelowsetpoint != TempFloat) {             // only write to eeprom if value is different
    EEPROM.put(10, relayonpointbelowsetpoint);               // i have no idea wat eeprom adress to use just jump to 10
    u8x8.setCursor(0, 0);
    u8x8.print(F("Saving to EEPROM"));
    u8x8.setCursor(0, 2);
    u8x8.print(TempFloat);
    u8x8.print(F(" new= "));
    u8x8.print(relayonpointbelowsetpoint);
    for (int i = 0; i < 100; i++)Serial.println(F("relayonpointbelowsetpoint DATA WRITEN / SAVED TO EEPROM "));
    u8x8.clear();
  }






  //4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
  //above set above set above set above set above set above set above set above set above set above set above set above set
  TempLong = millis();  //reset innactive time counter
  if (menu == 4) {
    u8x8.setCursor(0, 0);
    u8x8.print(F("4 Above Set"));
    u8x8.setCursor(0, 1);
    u8x8.print(relayoffabovesetpoint);
  }
  while (menu == 4) {
    if ((millis() - TempLong) > 10000) {
      TimeOut();
      break;
    }

    float rval;
    if ( rval = read_rotary() ) {
      relayoffabovesetpoint  = relayoffabovesetpoint  + (rval / 10);
      TempLong = millis();  //reset innactive time counter
      u8x8.setCursor(0, 1);
      u8x8.print(relayoffabovesetpoint);
      u8x8.print(F(" "));
      if (relayoffabovesetpoint > 2)relayoffabovesetpoint = 2;
      if (relayoffabovesetpoint < 0)relayoffabovesetpoint = 0;
    }

    if (!SetButton()) {              //if !=not setbutton pressed
      while (SetButton() == LOW); // wait for release button do not fly trough all the menus
      menu = 5;
      u8x8.clear();
      delay(250);
    }
  }

  EEPROM.get(15, TempFloat);                         // limmited write to eeprom = read is unlimmited
  if (relayoffabovesetpoint != TempFloat) {             // only write to eeprom if value is different
    EEPROM.put(15, relayoffabovesetpoint);               // i have no idea wat eeprom adress to use just jump to 5
    u8x8.setCursor(0, 0);
    u8x8.print(F("Saving to EEPROM"));
    u8x8.setCursor(0, 2);
    u8x8.print(TempFloat);
    u8x8.print(F(" new= "));
    u8x8.print(relayoffabovesetpoint);
    for (int i = 0; i < 100; i++)Serial.println(F("relayoffabovesetpoint DATA WRITEN / SAVED TO EEPROM "));
    u8x8.clear();
  }





  //5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-
  TempLong = millis();  //reset innactive time counter
  if (menu == 5) {
    u8x8.setCursor(0, 0);
    u8x8.print(F("5 MaxT 2SetPoint"));
    u8x8.setCursor(0, 1);
    u8x8.print(MaxTime2SetPoint );
    u8x8.print(F(" "));
  }
  while (menu == 5) {
    if ((millis() - TempLong) > 10000) {
      TimeOut();
      break;
    }

    float rval;
    if ( rval = read_rotary() ) {
      MaxTime2SetPoint  = MaxTime2SetPoint  + rval;
      TempLong = millis();  //reset innactive time counter
      u8x8.setCursor(0, 1);
      u8x8.print(MaxTime2SetPoint );
      u8x8.print(F(" "));
      if (MaxTime2SetPoint > MaxTimeRelayMayBeonInSeconds)MaxTime2Set<wbr />Point = MaxTimeRelayMayBeonInSeconds;
      if (MaxTime2SetPoint < 0)MaxTime2SetPoint = 0;
    }

    if (!SetButton()) {
      while (SetButton() == LOW); // wait for release button do not fly trough all the menus
      menu = 6;
      u8x8.clear();
      delay(250);
    }
  }


  EEPROM.get(40, TempInt);                         // limmited write to eeprom = read is unlimmited
  if (MaxTime2SetPoint != TempInt) {             // only write to eeprom if value is different
    EEPROM.put(40, MaxTime2SetPoint);               // i have no idea wat eeprom adress to use just jump to 10
    u8x8.setCursor(0, 0);
    u8x8.print(F("Saving to EEPROM"));
    u8x8.setCursor(0, 2);
    u8x8.print(TempInt);
    u8x8.print(F(" new= "));
    u8x8.print(MaxTime2SetPoint);
    for (int i = 0; i < 100; i++)Serial.println(F("MaxTime2SetPoint DATA WRITEN / SAVED TO EEPROM "));
    u8x8.clear();
  }







  //6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-
  //max t relay max t relay max t relay max t relay max t relay max t relay max t relay max t relay max t relay max t relay
  TempLong = millis();  //reset innactive time counter
  if (menu == 6) {
    u8x8.setCursor(0, 0);
    u8x8.print(F("6 Max T Relay on"));
    u8x8.setCursor(0, 1);
    u8x8.print(MaxTimeRelayMayBeonInSeconds);
  }
  while (menu == 6) {
    if ((millis() - TempLong) > 10000) {
      TimeOut();
      break;
    }

    float rval;
    if ( rval = read_rotary() ) {
      MaxTimeRelayMayBeonInSeconds  = MaxTimeRelayMayBeonInSeconds  + rval;
      TempLong = millis();  //reset innactive time counter
      u8x8.setCursor(0, 1);
      u8x8.print(MaxTimeRelayMayBeonInSeconds)<wbr />;
      u8x8.print(F(" "));
      if (MaxTimeRelayMayBeonInSeconds < 30)MaxTimeRelayMayBeonInSeconds = 30;
      if (MaxTimeRelayMayBeonInSeconds > 3600)MaxTimeRelayMayBeonInSeconds = 3600;
    }

    if (!SetButton()) {                //if !=not setbutton pressed
      while (SetButton() == LOW); // wait for release button do not fly trough all the menus
      menu = 7;
      u8x8.clear();
      delay(250);
    }
  }

  EEPROM.get(20, TempInt);                         // limmited write to eeprom = read is unlimmited
  if (MaxTimeRelayMayBeonInSeconds != TempInt) {             // only write to eeprom if value is different
    EEPROM.put(20, MaxTimeRelayMayBeonInSeconds);               // i have no idea wat eeprom adress to use just jump to 10
    u8x8.setCursor(0, 0);
    u8x8.print(F("Saving to EEPROM"));
    u8x8.setCursor(0, 2);
    u8x8.print(TempInt);
    u8x8.print(F(" new= "));
    u8x8.print(MaxTimeRelayMayBeonInSeconds)<wbr />;
    for (int i = 0; i < 100; i++)Serial.println(F("MaxTimeRelayMayBeonInSeconds DATA WRITEN / SAVED TO EEPROM "));
    u8x8.clear();
  }







  //7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-
  //CoolorHeat CoolorHeat CoolorHeat CoolorHeat CoolorHeat CoolorHeat
  TempLong = millis();  //reset innactive time counter
  if (menu == 7) {
    u8x8.setCursor(0, 0);
    u8x8.print(F("7 Cool / Heat"));
    u8x8.setCursor(0, 1);
    if (CoolorHeat == 1)u8x8.print(F("    COOL    "));
    if (CoolorHeat == 2)u8x8.print(F("    HEAT    "));
  }
  while (menu == 7) {
    if ((millis() - TempLong) > 10000) {
      TimeOut();
      break;
    }

    float rval;
    if ( rval = read_rotary() ) {
      CoolorHeat  = CoolorHeat  + rval;
      TempLong = millis();  //reset innactive time counter
      u8x8.setCursor(0, 1);
      u8x8.print(CoolorHeat);
      u8x8.print(F(" "));
      if (CoolorHeat < 1)CoolorHeat = 2;
      if (CoolorHeat > 2)CoolorHeat = 1;
      u8x8.setCursor(0, 1);
      if (CoolorHeat == 1)u8x8.print(F("    COOL    "));
      if (CoolorHeat == 2)u8x8.print(F("    HEAT    "));
    }

    if (!SetButton()) { //if !=not setbutton pressed
      while (SetButton() == LOW); // wait for release button do not fly trough all the menus
      menu = 8;
      u8x8.clear();
      delay(250);
    }
  }

  EEPROM.get(25, TempByte);                         // limmited write to eeprom = read is unlimmited
  if (CoolorHeat != TempByte) {                     // only write to eeprom if value is different
    EEPROM.put(25, CoolorHeat);                     // i have no idea wat eeprom adress to use just jump to 10
    u8x8.setCursor(0, 0);
    u8x8.print(F("Saving to EEPROM"));
    u8x8.setCursor(0, 2);
    u8x8.print(TempByte);
    u8x8.print(F(" new= "));
    if (CoolorHeat == 1)u8x8.print(F("COOL"));
    if (CoolorHeat == 2)u8x8.print(F("HEAT"));
    for (int i = 0; i < 100; i++)Serial.println(F("Cool/Heat DATA WRITEN / SAVED TO EEPROM "));
    u8x8.clear();
  }






  //8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-
  TempLong = millis();  //reset innactive time counter
  if (menu == 8) {
    u8x8.setCursor(0, 0);
    u8x8.print(F("8 Low Temp Alarm"));
    u8x8.setCursor(0, 1);
    u8x8.print(LowTempAlarmVal );
    u8x8.print(F(" "));
  }
  while (menu == 8) {
    if ((millis() - TempLong) > 10000) {
      TimeOut();
      break;
    }

    float rval;
    if ( rval = read_rotary() ) {
      LowTempAlarmVal  = LowTempAlarmVal  + rval;
      TempLong = millis();  //reset innactive time counter
      u8x8.setCursor(0, 1);
      u8x8.print(LowTempAlarmVal );
      u8x8.print(F(" "));
      if (LowTempAlarmVal > MaxTemp)LowTempAlarmVal = MaxTemp;
      if (LowTempAlarmVal < MinTemp)LowTempAlarmVal = MinTemp;
    }

    if (!SetButton()) {
      while (SetButton() == LOW); // wait for release button do not fly trough all the menus
      menu = 9;
      u8x8.clear();
      delay(250);
    }
  }


  EEPROM.get(35, TempInt);                         // limmited write to eeprom = read is unlimmited
  if (LowTempAlarmVal != TempInt) {             // only write to eeprom if value is different
    EEPROM.put(35, LowTempAlarmVal);               // i have no idea wat eeprom adress to use just jump to 10
    u8x8.setCursor(0, 0);
    u8x8.print(F("Saving to EEPROM"));
    u8x8.setCursor(0, 2);
    u8x8.print(TempInt);
    u8x8.print(F(" new= "));
    u8x8.print(LowTempAlarmVal);
    for (int i = 0; i < 100; i++)Serial.println(F("LowTempAlarmVal DATA WRITEN / SAVED TO EEPROM "));
    u8x8.clear();
  }






  //9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-
  TempLong = millis();  //reset innactive time counter
  if (menu == 9) {
    u8x8.setCursor(0, 0);
    u8x8.print(F("9 HighTemp Alarm"));
    u8x8.setCursor(0, 1);
    u8x8.print(HighTempAlarmVal );
  }
  while (menu == 9) {
    if ((millis() - TempLong) > 10000) {
      TimeOut();
      break;
    }

    float rval;
    if ( rval = read_rotary() ) {
      HighTempAlarmVal  = HighTempAlarmVal  + rval;
      TempLong = millis();  //reset innactive time counter
      u8x8.setCursor(0, 1);
      u8x8.print(HighTempAlarmVal );
      u8x8.print(F(" "));
      if (HighTempAlarmVal > MaxTemp)HighTempAlarmVal = MaxTemp;
      if (HighTempAlarmVal < MinTemp)HighTempAlarmVal = MinTemp;
    }

    if (!SetButton()) {                     //if !=not setbutton pressed
      while (SetButton() == LOW); // wait for release button do not fly trough all the menus
      menu = 10;
      u8x8.clear();
      delay(250);
    }
  }

  EEPROM.get(30, TempInt);                         // limmited write to eeprom = read is unlimmited
  if (HighTempAlarmVal != TempInt) {             // only write to eeprom if value is different
    EEPROM.put(30, HighTempAlarmVal);               // i have no idea wat eeprom adress to use just jump to 10
    u8x8.setCursor(0, 0);
    u8x8.print(F("Saving to EEPROM"));
    u8x8.setCursor(0, 2);
    u8x8.print(TempInt);
    u8x8.print(F(" new= "));
    u8x8.print(HighTempAlarmVal);
    for (int i = 0; i < 100; i++)Serial.println(F("HighTempAlarmVal DATA WRITEN / SAVED TO EEPROM "));
    u8x8.clear();
  }





  //10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10
  TempLong = millis();  //reset innactive time counter
  yesorno = 2;
  if (menu == 10) {
    u8x8.setCursor(0, 0);
    u8x8.print(F("10 Factory Reset"));
    u8x8.setCursor(6, 2);
    if (yesorno == 1)u8x8.print(F("YES"));
    if (yesorno == 2)u8x8.print(F("NO "));
  }
  while (menu == 10) {
    if ((millis() - TempLong) > 10000) {
      TimeOut();
      break;
    }

    float rval;
    if ( rval = read_rotary() ) {
      yesorno  = yesorno  + rval;
      TempLong = millis();  //reset innactive time counter
      if (yesorno < 1)yesorno = 2;
      if (yesorno > 2)yesorno = 1;
      u8x8.setCursor(6, 2);
      if (yesorno == 1)u8x8.print(F("YES"));
      if (yesorno == 2)u8x8.print(F("NO "));
    }


    if (!digitalRead(2) && yesorno == 1) {
      EEPROM.put(0, 30.00);         // setpoint
      EEPROM.put(5, 0.00);          // callibration offset
      EEPROM.put(10, -0.3);         // below on
      EEPROM.put(15, 0.3);          // above off
      EEPROM.put(20, 600);          // max time in seconds relay on
      EEPROM.put(25, 2);            // 1=cool 2=heat
      EEPROM.put(30, 90);           // high temp alarm
      EEPROM.put(35, 20);           // low temp alarm
      EEPROM.put(40, 300);
      u8x8.clear();
      u8x8.setCursor(0, 0);
      u8x8.print(F("Saving to EEPROM"));
      for (int i = 0; i < 100; i++)Serial.println(F(" valeus restored to factory settings "));
      // read stored valeus from eeprom
      EEPROM.get(0, SwitchOnTemp);
      EEPROM.get(5, CalibrationOffset);
      EEPROM.get(10, relayonpointbelowsetpoint);
      EEPROM.get(15, relayoffabovesetpoint);
      EEPROM.get(20, MaxTimeRelayMayBeonInSeconds);
      EEPROM.get(25, CoolorHeat);
      EEPROM.get(30, HighTempAlarmVal);
      EEPROM.get(35, LowTempAlarmVal);
      EEPROM.get(40, MaxTime2SetPoint);
      delay(1000);
      menu = 11;
      u8x8.clear();

    }

    if (!digitalRead(2) && yesorno == 2) { //no + button
      while (SetButton() == LOW); // wait for release button do not fly trough all the menus
      menu = 11;
      u8x8.clear();
      delay(250);
    }

  }





  //11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11-11
  TempLong = millis();  //reset innactive time counter
  while (menu == 11) {
    if ((millis() - TempLong)  > 1200000) {
      TimeOut();
      break;
    }
    
    // Arduino UpTime RunTime
    // runtime since boot/start days hours minutes seconds
    // micros has a 70 minut overflow faster for testing
    // millis has a 50 day overflow
    // ISR timer 1 overflow counter?
    // interrupt service routine to count the number of overflows of timer 0 1 2 ???
    // is there something to count the number of  overflows
    // i do not know i am a beginner newbie
    
    Serial.println(F(" rumtime menu"));
    u8x8.setCursor(0, 0);
    u8x8.print(F("11 RunTime"));
    u8x8.setCursor(3, 2);
    u8x8.print((micros() / 86400000) % 365);   //should be millis() micros overflow is faster
    u8x8.print(" ");
    u8x8.print((micros() / 3600000) % 24);    //should be millis() micros overflow is faster
    u8x8.print(":");
    u8x8.print((micros() / 60000) % 60);       //should be millis() micros overflow is faster
    u8x8.print(":");
    u8x8.print((micros() / 1000) % 60);       //should be millis() micros overflow is faster
    u8x8.print("  ");
    u8x8.setCursor(0, 4);
    u8x8.print(micros());
    u8x8.setCursor(0, 5);
    u8x8.print(F("Copyright DLD"));
    u8x8.setCursor(0, 6);
    u8x8.print(F("Luberth Dijkman"));
    u8x8.setCursor(0, 7);
    u8x8.print(F("The Netherlands"));
    if (SetButton() == LOW) {
      while (SetButton() == LOW); // wait for release button do not fly trough all the menus
      menu = 0;
      u8x8.clear();
      delay(250);
    }

  }





  Read_NTC_Thermistor();

  //Vo = analogRead(ThermistorPin);
  R2 = R1 * (1023.0 / (float)Vo - 1.0);
  logR2 = log(R2);
  T = (1.0 / (c1 + c2 * logR2 + c3 * logR2 * logR2 * logR2));
  Tc = T - 273.15 + CalibrationOffset;

  //Tf = (Tc * 9.0)/ 5.0 + 32.0; // fahrenheit


  // compare actualtemp to switchpoint with offsets
  //COOL COOL COOL COOL COOL COOL COOL COOL COOL COOL COOL COOL COOL COOL COOL COOL COOL COOL
  if (CoolorHeat == 1) {      // 1=cool 2=heat
    u8x8.setCursor(0, 7);
    u8x8.print(F("    Cool Mode   "));
    if (Tc < SwitchOnTemp + relayonpointbelowsetpoint) {
      RelaisState = 0;
    }
    if (Tc > SwitchOnTemp + relayoffabovesetpoint) {
      RelaisState = 1;
    }
  }
  //HEAT HEAT HEAT HEAT HEAT HEAT HEAT HEAT HEAT HEAT HEAT HEAT HEAT HEAT HEAT HEAT HEAT HEAT
  if (CoolorHeat == 2) {      // 1=cool 2=heat
    u8x8.setCursor(0, 7);
    u8x8.print(F("   Heat Mode    "));
    if (Tc < SwitchOnTemp + relayonpointbelowsetpoint) {
      RelaisState = 1;
    }
    if (Tc > SwitchOnTemp + relayoffabovesetpoint) {
      RelaisState = 0;
    }
  }

  if (Tc < LowTempAlarmVal) {
    for (int i = 0; i < 10; i++)Serial.println(F(" Alarm Temperature LOW "));
    u8x8.setCursor(0, 2);
    u8x8.print(F("Alarm Temp. LOW"));
    buzzer();   //passive buzzer on D8
    u8x8.setCursor(0, 2);
    u8x8.print(F("               "));
    digitalWrite(11, 1);
  } else {
    digitalWrite(11, 0);

  }

  if (Tc > HighTempAlarmVal) {
    for (int i = 0; i < 10; i++)Serial.println(F(" Alarm Temperature HIGH "));
    digitalWrite(12, 1);
    u8x8.setCursor(0, 2);
    u8x8.print(F("Alarm Temp. High"));
    buzzer();   //passive buzzer on D8
    u8x8.setCursor(0, 2);
    u8x8.print(F("                "));
  } else {
    digitalWrite(12, 0);
  }




  Serial.print(F("D10 "));
  Serial.print(RelaisState);

  Serial.print(F(" A0 "));
  Serial.print(Vo);
  Serial.print(F(" Temp "));
  Serial.print(Tc, 1);  // 1 decimal

  u8x8.setCursor(2, 1);
  u8x8.print(Tc, 1);
  u8x8.print(" C");//\337C Cdegree sign


  if (Vo <= 60) {
    for (int i = 0; i < 10; i++)Serial.println(F(" analogread < 60 ERROR LOW "));
    RelaisState = 0; //turn off relays
    u8x8.setCursor(0, 2);
    u8x8.print(F("  Sensor Loss  "));
    buzzer();   //passive buzzer on D8
    u8x8.setCursor(0, 2);
    u8x8.print(F("               "));
  }
  if (Vo >= 960) {
    for (int i = 0; i < 10; i++)Serial.println(F(" analogread > 960 ERROR HIGH "));
    RelaisState = 0; //turn off relays
    u8x8.setCursor(0, 2);
    u8x8.print(F(" Sensor Shorted "));
    buzzer();   //passive buzzer on D8
    u8x8.setCursor(0, 2);
    u8x8.print(F("                "));
  }



  //Serial.print("menu nr ");
  //Serial.print(menu);

  Serial.print(F(" Set "));
  Serial.print(SwitchOnTemp);
  u8x8.setCursor(10, 1);
  u8x8.print(SwitchOnTemp, 1);
  u8x8.print(" C");   //\337C Cdegree sign


  //Serial.print(" TempFloat ");
  //Serial.print(TempFloat);
  //Serial.print(" TempInt ");
  //Serial.print(TempInt);
  //Serial.print(" TempLong ");
  //Serial.print(TempLong);

  Serial.print(F(" Below "));
  Serial.print(relayonpointbelowsetpoint);<wbr />
  Serial.print(F(" Above "));
  Serial.print(relayoffabovesetpoint);

<wbr />
  Serial.print(F(" Offset "));
  Serial.print(CalibrationOffset);

  Serial.print(F(" Lalarm "));
  Serial.print(LowTempAlarmVal);
  Serial.print(F(" Halarm "));
  Serial.print(HighTempAlarmVal);

  if (RelaisState == 0) {
    digitalWrite(10, 0);
    starttime = millis();
  }
  if (RelaisState == 1 && digitalRead(10) == 0) {
    digitalWrite(10, 1);
    starttime = millis();
  }

  timeon =  (millis() - starttime) / 1000;
  Serial.print(F(" MaxT "));
  Serial.print(MaxTimeRelayMayBeonInSecond<wbr />s);

  Serial.print(F(" Ton "));
  Serial.print(timeon);

  if (RelaisState == 1 ) {
    u8x8.setCursor(0, 4);
    u8x8.print(timeon);
    u8x8.print(F(" Sec. ON "));
  } else {
    u8x8.setCursor(0, 4);
    u8x8.print(F("Relay OFF      "));
  }

  EEPROM.get(666, TempInt);
  Serial.print(F(" Devil "));
  Serial.println(TempInt);


  if (timeon > MaxTimeRelayMayBeonInSeconds) {            //if there is a sensor fail or heating fail
    for (int i = 0; i < 10; i++)Serial.println(F(" >>>>>>>> ERROR max time relay ON <<<<<<<<<"));
    //shutdown more??? relay should not be on so long
    u8x8.setCursor(0, 2);
    u8x8.print(F("MaxTime Relay ON"));
    buzzer();   //passive buzzer on D8
    u8x8.setCursor(1, 2);
    u8x8.print(F("                 "));
  }

  if (timeon > MaxTime2SetPoint) {            //
    for (int i = 0; i < 10; i++)Serial.println(F(" >>>>>>>> time on 2 desired setpoint to long <<<<<<<<<"));
    //shutdown more??? relay should not be on so long
    u8x8.setCursor(0, 2);
    u8x8.print(F("Time2 setpoint >"));
    buzzer();   //passive buzzer on D8
    u8x8.setCursor(1, 2);
    u8x8.print(F("                   "));

  }



  //delay(50);

  // if you change the program to make it do more or better
  // would like to know/share
  // https://m.facebook.com/luberth.dijkman
  // http://84.106.2.21:8888/forum/index.php?<wbr />action=view&id=296

}
//end loop







//maybe above code is better to read if i do button digitalread like this
boolean SetButton() {
  boolean sval;
  sval = digitalRead(2);
  if (sval == 0) {                 // make a buzz when button pressed
    tone(8, 200); //output D8 Hz
    delay(100);
    noTone(8);
    delay(250);
  }
  //Serial.print(F("SetButton="));
  //Serial.println(sval);
  return sval;
}

boolean PlusButton() {
  boolean sval;
  sval = digitalRead(3);
  Serial.print(F("PlusButton="));
  Serial.println(sval);
  return sval;
}

boolean MinButton() {
  boolean sval;
  sval = digitalRead(4);
  Serial.print(F("MinButton="));
  Serial.println(sval);
  return sval;
}

int Read_NTC_Thermistor() {
  for (int i = 0; i < 500; i++) {
    Vo = Vo + analogRead(A0);             // found temp value displayed bouncy noisy fluctuating
    delay(1);                             // do 500 analog ntc readings and divide by 200 to get an average
  }
  Vo = Vo / 500;
  return Vo;
}


void TimeOut() {
  u8x8.clear();  //exit menu if 20 seconds innactive
  u8x8.setCursor(0, 1);
  u8x8.print(F("     TimeOut    "));
  u8x8.setCursor(0, 2);
  u8x8.print(F("  Start Screen  "));
  delay(2000);
  u8x8.clear();
  menu = 0;
}





int8_t read_rotary() {
  static int8_t rot_enc_table[] = {0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0};

  // Robust Rotary encoder reading
  // Copyright John Main - best-microcontroller-projects.com
  // https://www.best-microcontroller-projects.com/rotary-encoder.html

  prevNextCode <<= 2;
  if (digitalRead(DATA)) prevNextCode |= 0x02;
  if (digitalRead(CLK)) prevNextCode |= 0x01;
  prevNextCode &= 0x0f;

  // If valid then store as 16 bit data.
  if  (rot_enc_table[prevNextCode] ) {
    store <<= 4;
    store |= prevNextCode;
    //if (store==0xd42b) return 1;
    //if (store==0xe817) return -1;
    if ((store & 0xff) == 0x2b) return -1;
    if ((store & 0xff) == 0x17) return 1;
  }
  return 0;

  // Robust Rotary encoder reading
  // Copyright John Main - best-microcontroller-projects.com
  // https://www.best-microcontroller-projects.com/rotary-encoder.html
}

void buzzer() {
  /* int i, t;
    for (t = 0; t < 1; t = t + 1) {
     //for (i = 7000; i > 1; i=i-1)tone(zoemer, i);
     //for (i = 1; i < 7000; i = i + 1)tone(8, i);   //passive buzzer on D8
     tone(8, 1000, 300);  //output D8 1000Hz 300Ms
     delay(500);
     tone(8, 500, 300); //output D8 500Hz 300Ms
     delay(500);
     noTone(8);
     delay(200);
    }
    noTone(8);
    //return 0;
  */
  // iterate over the notes of the melody:
  for (int thisNote = 0; thisNote < 8; thisNote++) {

    // to calculate the note duration, take one second divided by the note type.
    //e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
    int noteDuration = 1000 / noteDurations[thisNote];
    tone(8, melody[thisNote], noteDuration);

    // to distinguish the notes, set a minimum time between them.
    // the note's duration + 30% seems to work well:
    int pauseBetweenNotes = noteDuration * 1.30;
    delay(pauseBetweenNotes);
    // stop the tone playing:
    noTone(8);
  }
}












// it is mostly air i live on
// but i could use your support
// a nickle or dime for every device you put this code on
// would be appreciated http://paypal.me/pools/c/8amUN5rgb9
// more is allowed









some pieces of output from arduino serial terminal monitor


switch  D10 on at 29.7  set 30 below -0.3

D10 0 A0 561.82 Temp 29.8 Set 30.00 Below -0.30 Above 0.30 Offset 0.00 Lalarm 20 Halarm 90 MaxT 600 Ton 0 Devil 666
D10 0 A0 561.38 Temp 29.8 Set 30.00 Below -0.30 Above 0.30 Offset 0.00 Lalarm 20 Halarm 90 MaxT 600 Ton 0 Devil 666
D10 0 A0 561.06 Temp 29.7 Set 30.00 Below -0.30 Above 0.30 Offset 0.00 Lalarm 20 Halarm 90 MaxT 600 Ton 0 Devil 666
D10 1 A0 560.59 Temp 29.7 Set 30.00 Below -0.30 Above 0.30 Offset 0.00 Lalarm 20 Halarm 90 MaxT 600 Ton 0 Devil 666
D10 1 A0 559.83 Temp 29.6 Set 30.00 Below -0.30 Above 0.30 Offset 0.00 Lalarm 20 Halarm 90 MaxT 600 Ton 0 Devil 666
D10 1 A0 559.41 Temp 29.6 Set 30.00 Below -0.30 Above 0.30 Offset 0.00 Lalarm 20 Halarm 90 MaxT 600 Ton 1 Devil 666




switch  D10 off at 30.3  set 30 above 0.3

D10 1 A0 559.46 Temp 29.6 Set 30.00 Below -0.30 Above 0.30 Offset 0.00 Lalarm 20 Halarm 90 MaxT 600 Ton 9 Devil 666
D10 1 A0 562.13 Temp 29.8 Set 30.00 Below -0.30 Above 0.30 Offset 0.00 Lalarm 20 Halarm 90 MaxT 600 Ton 9 Devil 666
D10 1 A0 564.54 Temp 30.1 Set 30.00 Below -0.30 Above 0.30 Offset 0.00 Lalarm 20 Halarm 90 MaxT 600 Ton 10 Devil 666
D10 0 A0 566.88 Temp 30.3 Set 30.00 Below -0.30 Above 0.30 Offset 0.00 Lalarm 20 Halarm 90 MaxT 600 Ton 0 Devil 666
D10 0 A0 569.34 Temp 30.6 Set 30.00 Below -0.30 Above 0.30 Offset 0.00 Lalarm 20 Halarm 90 MaxT 600 Ton 0 Devil 666
D10 0 A0 571.33 Temp 30.8 Set 30.00 Below -0.30 Above 0.30 Offset 0.00 Lalarm 20 Halarm 90 MaxT 600 Ton 0 Devil 666



temp < alarmtemplow

 Alarm Temperature LOW 
 Alarm Temperature LOW 
D10 1 A0 463.66 Temp 19.9 Set 30.00 Below -0.30 Above 0.30 Offset 0.00 Lalarm 20 Halarm 90 MaxT 600 Ton 562 Devil 666
 Alarm Temperature LOW 
 Alarm Temperature LOW 



temp > alarmtemphigh

 Alarm Temperature HIGH 
 Alarm Temperature HIGH 
D10 0 A0 926.49 Temp 93.2 Set 30.00 Below -0.30 Above 0.30 Offset 0.00 Lalarm 20 Halarm 90 MaxT 600 Ton 0 Devil 666
 Alarm Temperature HIGH 
 Alarm Temperature HIGH 




max time relay on > setting 600 sec

D10 1 A0 470.77 Temp 20.6 Set 30.00 Below -0.30 Above 0.30 Offset 0.00 Lalarm 20 Halarm 90 MaxT 600 Ton 600 Devil 666
D10 1 A0 470.76 Temp 20.6 Set 30.00 Below -0.30 Above 0.30 Offset 0.00 Lalarm 20 Halarm 90 MaxT 600 Ton 600 Devil 666
D10 1 A0 470.79 Temp 20.6 Set 30.00 Below -0.30 Above 0.30 Offset 0.00 Lalarm 20 Halarm 90 MaxT 600 Ton 601 Devil 666
 >>>>>>>> ERROR max time relay ON <<<<<<<<<
 >>>>>>>> ERROR max time relay ON <<<<<<<<<
 >>>>>>>> ERROR max time relay ON <<<<<<<<<
 >>>>>>>> ERROR max time relay ON <<<<<<<<<
 >>>>>>>> ERROR max time relay ON <<<<<<<<<
 >>>>>>>> ERROR max time relay ON <<<<<<<<<
 >>>>>>>> ERROR max time relay ON <<<<<<<<<
 >>>>>>>> ERROR max time relay ON <<<<<<<<<
 >>>>>>>> ERROR max time relay ON <<<<<<<<<
 >>>>>>>> ERROR max time relay ON <<<<<<<<<
D10 1 A0 470.81 Temp 20.6 Set 30.00 Below -0.30 Above 0.30 Offset 0.00 Lalarm 20 Halarm 90 MaxT 600 Ton 602 Devil 666
 >>>>>>>> ERROR max time relay ON <<<<<<<<<
 >>>>>>>> ERROR max time relay ON <<<<<<<<<



SwitchOnTemp 30.00
SwitchOnTemp 30.00


CalibrationOffset 0.00
CalibrationOffset 0.00


relayoffabovesetpoint 0.30
relayoffabovesetpoint 0.30


maximum time the relay may be on in seconds 600
maximum time the relay may be on in seconds 600


cool / heat / ldr on dark / ldr on light 
cool / heat / ldr on dark / ldr on light 


High Temp alarm  90
High Temp alarm  90


Low Temp alarm  20
Low Temp alarm  20
 
 
 factory reset press + and - here together to factory reset  or setbutton to exit menu
 factory reset press + and - here together to factory reset  or setbutton to exit menu


output from arduino serial terminal monitor



WARNING!
DO NOT power
the LCD and relais board
from the NANO 5vdc voltage regulator
is to much for the NANO!












W1209 thermostat manual
The Digital thermostat specification XH - W1209
1. The technical parameters
Control range: - 50 to 110 °C
Resolution: -9.9 to 99.9 at 0.1℃& other temperature section at 1 °C
Temperature measuring accuracy: 0.1 °C
Control Accuracy: 0.1 °C
Accuracy of difference: 0.1 °C
Refresh rate: 0.5 S
High temperature alarm: 0-110 °C
Input power: DC 12V
Measuring input: NTC (10K 0. 5%) waterproof type sensor
Relay Output: 10A
Environmental requirements: - 10 to 60 °C, humidity 20% to 85%
Size: 48 * 40 mm
The machine power consumption:
Static current: ≤ 35 MA
Attracting current: ≤ 65 MA
2. Use method
Connect the power supply and load, for a power supply, the
controller can be displayed for measuring temperature, according to
a SET key, the screen flashing temperature; Press + - to SET the
required temperature, SET according to a SET confirmed return, after 
the completion of the controller according to the SET automatically
relay on and off!
The thermostat for 10 A output relay, meet all kinds of high power
load, please ensure that the circuit is correct.
3. The indicator lights, digital tube status
Light: light off shows relay disconnect, normally on show that the
relay has closed


***********************************************************************
For sensing: digital tube display “'LLL”; display “HHH” is beyond the
measuring range thermostat will force disconnect relay
     NOT TRUE ON MY W1209 THERMOSTAT PCB'S / PRINTS FROM ALIEXPRES
     IF RELAY IS ON 
     AND SENSOR FAILS, BREAKS, SHORTS OR DISCONNECTS
     THEN RELAIS IS ON FOREVER 
     BURNS YOUR HOUSE / FACTORY DOWN
     
     WHAT I SEE ON THE WEB THERE ARE  SOME CLONES/DIFFERENT MAKES 
     WICH ALL LOOK THE SAME
     BUT SOME HAVE STM8 OTHER HAVE NUVOTON NUOVO MICROPROCESSORS
     AND MAYBE PROGRAM CODE VARIATIONS (I CAN NOT FIND SOURCECODE ON THE WEB)
     
     I THINK THE CODE ON MY W1209 THERMOSTAT PRINTS COULD BE SAFER
***********************************************************************



4. The parameter function
Long press SET 5 seconds can be set to enter the main menu; press +
- switching P0...P6 long press SET or 10 seconds without buttons
controller automatically confirm return.
 Setting Table
code Code instructions Setting range Factory set-up

P0 Refrigeration/heating C/H default Cool

P1 Return difference set 0.1 ... 15  default 2 degrees switch
 
P2 Limit the highest value
(temp. control)
110 110

P3 Limit the lowest
value(temp. control)
-50 -50

P4 The temp. calibration -7.0 ... +7.0 °C default 0 temperature offset / adjust actual temperature

P5 Delay relay start time 0-10 minutes  default 0

P6 High temp. alarm 0-110 °C default off if alarm display --- and turns relay off

P REQUEST? MAXIMUM TIME ALLOWED FOR RELAYS CONTINU ON
  IF TIME RELAIS ON TOO LONG THEN ERROR AND TURN OFF RELAIS

 
Long press “+-” to start up can restore the factory defaults on powerup.








3d print a case
possible this case might fit
https://www.thingiverse.com/thing:3270498
Arduino dusk/dawn clock timer
https://www.instructables.com/id/Arduino-Duskdawn-Clock-Timer/
https://github.com/escheppink/Arduino-dusk-dawn-clock-timer
by escheppink Dec 14, 2018

3d print a case
possible this case might fit
https://www.thingiverse.com/thing:3270498
Arduino dusk/dawn clock timer
by escheppink Dec 14, 2018
https://www.instructables.com/id/Arduino-Duskdawn-Clock-Timer/
https://github.com/escheppink/Arduino-dusk-dawn-clock-timer










End of Message, Thanks For Viewing! ☺
Tip: if your watching on your phone or tablet ⁝ add / save to homescreen and you get a nice icon its Free!
Tip: on your computer or laptop do not forget to bookmark this page its Free!
BookMark ShortCut Keys press ctrl+d on your keyboard




-

-

Reply to this Message







POLL / VOTE
Did you like this Page id=296 ?

NO:         YES:




   


Design a Bit like ForumOne 4.0 WayBack 1999 ©
Always Read the Small print?!



http://forum.luberth.com - - http://www.luberth.com/forum/

NO COOKIES !?

thanks for your support
Thank You!




Co2 FootPrint WebServer



                         My Cheap Chinese Friend Ali     
Copyright Luberth Dijkman 2018 ... 2019




GoodBye Galaxy!