// https://github.com/ldijkman/arduino_w1209_thermostat_clone
// 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-thermistor-temperature-sensor-tutorial/
// https://github.com/tehniq3/DS18B20_thermostat_4digit_7segment_led_display/blob/master/4dig7segm_ac_18b20_thermostat_ver4m7.ino
// Robust Rotary encoder reading
// Copyright John Main - best-microcontroller-projects.com
// https://www.best-microcontroller-projects.com/rotary-encoder.html
//
// this code came from
// http://sticker.tk/forum/index.php?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/LDijkman
// 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/LDijkman
//
// 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
// http://sticker.tk/forum/index.php?action=view&id=296
#include <EEPROM.h>
//#include <LiquidCrystal_I2C.h> https://github.com/fmalpartida/New-LiquidCrystal
//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/toneMelody
// die zien we nooit meer terug cocktail trio vlooiencircus 1965 https://www.youtube.com/watch?v=DizwZ0uOX5A
// 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_SW_I2C u8x8(12, 11, U8X8_PIN_NONE);
U8X8_SSD1306_128X64_NONAME_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
#define 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_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)MaxTime2SetPoint = 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);
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);
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);
Serial.print(F(" Above "));
Serial.print(relayoffabovesetpoint);
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(MaxTimeRelayMayBeonInSeconds);
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://sticker.tk/forum/index.php?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/LDijkman
// more is allowed
// https://github.com/ldijkman/arduino_w1209_thermostat_clone