#include <avr/wdt.h>
#include <EEPROM.h>
#include <LiquidCrystal.h>
#include "eeWrite.h"
#define ThermistorPIN_0 1
// A, B, C and D constants are used for the therimostor calculations. Values found o NTC's Datasheet
const float BETA = 3950;
//Three push switches
#define sw_0 A5
#define sw_1 A4
#define sw_2 A3
#define output 9
#define powerled 8
#define summerled 10
#define PAD_Res_0 9970.0 // balance/pad resistor value.
#define Rn 10000.0 // Termistor at 25 degrees Celcius.
struct config_t
{
float setpoint_c;
float hysteresis_c;
boolean scale_c;
boolean power_c;
boolean stateonpowerfail_c;
boolean summermode_c;
} config;
boolean scale = false; //Scale selected. Celcius or Fahrenheit.
boolean power = false;
boolean stateonpowerfail = false; //Remember the state after power fail.
boolean somethingchanged = false;
boolean summermode = false;
float setpoint = 0.0;
float hysteresis = 0.5;
float Temp; // Temperature holding variable.
float max_t; // Maximum temperature variable.
float min_t; // Minimum temperature variable.
int delay_1 = 300; //Some delay time
int menu = 0;
int counter_0 = 0;
int counter_1 = 0;
unsigned long currentMillis;
//unsigned long previousMillis;
unsigned long time;
char symbol = 'C';
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
void eezero (size_t var){
int i;
for (i=1; i < var+10; i++) {
EEPROM.write(i,0x00);
}
}
//Function used to convert Celcius to Fahrenheit.
void convert(boolean scale) {
float tmp1;
tmp1=setpoint;
if (scale == true){
tmp1 = (9.0/5.0)*tmp1+32;
setpoint=tmp1;
} else {
tmp1 = 5.0/9.0*(tmp1-32);
setpoint=tmp1;
}
write_c();
}
//Function used to calculate the temperature based ont hte thermostor's value.
float Thermistor(int RawADC, float Res, boolean Scale) {
float tmp; //Temporary variable.
symbol = 'C';
tmp = 1 / (log(1 / (1023. / RawADC - 1)) / BETA + 1.0 / 298.15) - 273.15;
if (scale == true) {
tmp = (9.0/5.0)*tmp+32;
}
return tmp; // Return the temperature.
}
char Symbol() {
if (scale == true) {
return 'F';
} else {
return 'C';
}
}
void read_c(){
EEPROM_readAnything(0, config);
setpoint = config.setpoint_c;
hysteresis = config.hysteresis_c;
scale = config.scale_c;
stateonpowerfail = config.stateonpowerfail_c;
summermode = config.summermode_c;
if (stateonpowerfail == true) power = config.power_c;
}
void write_c(){
config.setpoint_c = setpoint;
config.hysteresis_c = hysteresis;
config.scale_c = scale;
config.power_c = power;
config.stateonpowerfail_c = stateonpowerfail;
config.summermode_c = summermode;
EEPROM_writeAnything(0, config);
}
//Function used to increase or decrease a variable by 0.1.
float change(boolean UP, float var){
if (UP == true) {
var=var + 0.1;
} else {
var=var - 0.1;
}
write_c;
return var;
}
void minmax(float temp) {
}
void setup() {
pinMode(sw_0, INPUT_PULLUP);
pinMode(sw_1, INPUT_PULLUP);
pinMode(sw_2, INPUT_PULLUP);
pinMode(output, OUTPUT);
pinMode(powerled,OUTPUT);
pinMode(summerled,OUTPUT);
wdt_enable(WDTO_2S); //Enabling Watch dog in case something goes wrong and the program stuck.
if (EEPROM.read(0) == 0xFF) eezero(sizeof(config));
read_c();
lcd.begin(16, 2);
lcd.clear();
digitalWrite(output, LOW);
}
void loop() {
wdt_reset(); //Pat pat, good dog.
int sign;
digitalWrite(powerled, power);
digitalWrite(summerled, summermode);
if (summermode == false) {
sign=1;
} else {
sign=-1;
}
somethingchanged = false;
//Read the thermistor every 1500 msecs.
if (millis() - time >= 1500) {
Temp=Thermistor(analogRead(ThermistorPIN_0), PAD_Res_0, scale);
if (sign*Temp <= sign*(setpoint - sign*hysteresis) && digitalRead(output) == LOW && power == true) {
counter_1++;
} else if (sign*Temp >= sign*setpoint && digitalRead(output) == HIGH || power == false){
counter_1--;
if (counter_1 < 0) counter_1 = 0;
}
if (counter_1 > 2) { //Wait 2 read sensor cycles to make sure
digitalWrite(output, HIGH); //that temperature reached setpoint. This
} else if (counter_1 <= 0){ //prevents quick on-off of the output.
digitalWrite(output, LOW);
counter_1=0;
}
time = millis();
}
if (digitalRead(sw_2) == LOW) {
menu++;
delay(400);
lcd.clear();
currentMillis = millis(); //Reset the currentMillis variable, wait another 3000 msec.
}
if (menu > 4) menu = 0;
if (digitalRead(sw_0) == LOW) {
if (counter_0 > 10) delay_1 = 30; //Cuntiniously pusshing the switch, make things faster
currentMillis=millis(); //Reset the currentMillis variable, wait another 3000 msec.
switch (menu) {
case 4:
stateonpowerfail=!stateonpowerfail;
break;
case 3:
scale=!scale;
convert(scale);
break;
case 2:
hysteresis=change(true,hysteresis);
if (hysteresis > 10.0) hysteresis = 10.0;
break;
case 1:
setpoint=change(true,setpoint);
if (scale == false && setpoint > 80.0) {
setpoint = 80.0;
} else if (scale == true && setpoint > 176.0) {
setpoint = 176.0;
}
break;
case 0:
power=!power;
break;
}
delay(delay_1);
somethingchanged = true;
}
if (digitalRead(sw_1) == LOW) {
if (counter_0 > 10) delay_1 = 30; //Cuntiniously pusshing the switch, make things faster
currentMillis=millis(); //Reset the currentMillis variable, wait another 3000 msec.
switch (menu) {
case 4:
stateonpowerfail=!stateonpowerfail;
break;
case 3:
scale=!scale;
convert(scale);
break;
case 2:
hysteresis=change(false,hysteresis);
if (hysteresis < 0.0) hysteresis = 0.0;
break;
case 1:
setpoint=change(false,setpoint);
if (setpoint < -40.0) setpoint = -40.0;
break;
case 0:
summermode=!summermode;
//digitalWrite(summerled,summermode);
break;
}
//write_c();
delay(delay_1);
somethingchanged = true;
}
switch (menu) {
case 4:
lcd.setCursor(0, 0);
lcd.print("Save State");
lcd.setCursor(0, 1);
if (stateonpowerfail == true) {
lcd.print("Yes");
} else {
lcd.print("No");
}
lcd.print(" ");
if (millis() - currentMillis > 3000) menu = 0; //Reset the currentMillis variable, wait another 4000 msec.
break;
case 3:
lcd.setCursor(0, 0);
lcd.print("Scale: C, F");
lcd.setCursor(0, 1);
lcd.print(Symbol());
lcd.print(" ");
if (millis() - currentMillis > 3000) menu = 0; //Reset the currentMillis variable, wait another 4000 msec.
break;
case 2:
lcd.setCursor(0, 0);
lcd.print("Hysteresis");
lcd.setCursor(0, 1);
lcd.print(hysteresis,1);
lcd.print(" ");
lcd.print(Symbol());
lcd.print(" ");
if (millis() - currentMillis > 3000) menu = 0; //Reset the currentMillis variable, wait another 4000 msec.
break;
case 1:
lcd.setCursor(0, 0);
lcd.print("Set value");
lcd.setCursor(0, 1);
lcd.print(setpoint,1);
lcd.print(" ");
lcd.print(Symbol());
lcd.print(" ");
if (millis() - currentMillis > 3000) menu = 0; //Reset the currentMillis variable, wait another 4000 msec.
break;
case 0:
lcd.setCursor(0, 0);
lcd.print("Temperature");
lcd.setCursor(0, 1);
if (Temp < 10 && Temp > -10 ){
lcd.print(" ");
}
lcd.print(Temp,1);
lcd.print(" ");
lcd.print(Symbol());
lcd.print(" ");
if (power == true) {
lcd.print("On ");
} else {
lcd.print("Off");
}
lcd.print(" ");
if (summermode == true) {
lcd.print("S");
} else {
lcd.print("W");
lcd.print(" ");
}
lcd.print(" ");
}
//When UP, or DOWN switches are continiously pushed change the delay.
if (digitalRead(sw_0) == LOW || digitalRead(sw_1) == LOW) {
counter_0++;
somethingchanged = false; //Save after key is released.
}
else {
counter_0 = 0;
delay_1 = 300;
}
if (somethingchanged == true){
write_c();
}
}