// simple thermostat
const char *Version = "Thermostat 260106a";
#include <OneWire.h>
#include <DallasTemperature.h>
#include <LiquidCrystal_I2C.h>
#include <RTClib.h>
#define ONE_WIRE_BUS_1 3
#define TEMPERATURE_PRECISION 11 // 0.125deg resolution
OneWire oneWire_range (ONE_WIRE_BUS_1);
DallasTemperature dallasRange (&oneWire_range);
LiquidCrystal_I2C lcd (0X27, 20, 4);
RTC_DS3231 rtc;
const byte PinButs [] = { 6, 7, 8, 9, 10 };
const int Nbut = sizeof(PinButs);
byte butState [Nbut];
enum { Bsel, Bup, Bdown, Bright, Benter };
// -------------------------------------
struct Room {
DallasTemperature *sensor;
int setPt;
const char *desc;
float tempC;
bool on;
}
rooms [] {
{ &dallasRange, 20, "range" }
} ;
Room *pR = & rooms [0];
// -------------------------------------
char s [90];
char t [20];
char u [20];
// -----------------------------------------------------------------------------
int
chkButtons ()
{
for (unsigned n = 0; n < Nbut; n++) {
byte but = digitalRead (PinButs [n]);
if (butState [n] != but) { // state change
butState [n] = but;
delay (30); // debounce
if (LOW == but) // pressed
return n;
}
}
return -1;
}
// -----------------------------------------------------------------------------
const char *DayOfWeek [] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
char time [40];
void clock ()
{
DateTime now = rtc.now();
sprintf (time, " %10s %2d:%02d",
DayOfWeek [now.dayOfTheWeek ()], now.hour (), now.minute () );
}
// -----------------------------------------------------------------------------
void display ()
{
lcd.clear ();
lcd.setCursor (0, 0);
lcd.print (time);
lcd.setCursor (0, 1);
dtostrf (pR->tempC, 5, 1, t);
sprintf (s, "%s%c %3dC %s", t, pR->on?'^':' ', pR->setPt, pR->desc);
lcd.print (s);
}
// -----------------------------------------------------------------------------
void heating (
Room *pR,
bool req )
{
if (req)
pR->sensor->requestTemperatures ();
pR->tempC = pR->sensor->getTempCByIndex (0);
pR->on = pR->tempC < pR->setPt;
pR->sensor->requestTemperatures (); // for next measurement
}
// -----------------------------------------------------------------------------
void menu ()
{
switch (chkButtons ()) {
case Bsel:
break;
case Bup:
pR->setPt++;
Serial.println (pR->setPt);
break;
case Bdown:
Serial.println (pR->setPt);
pR->setPt--;
break;
case Bright:
break;
case Benter:
break;
}
}
// -----------------------------------------------------------------------------
unsigned long msec0;
unsigned long msec1;
void loop ()
{
unsigned long msec = millis ();
menu ();
if (msec - msec0 >= 500) {
msec0 = msec;
clock ();
display ();
}
if (msec - msec1 >= 10000) {
msec1 = msec;
heating (pR, 0);
}
}
// -----------------------------------------------------------------------------
void setup ()
{
Serial.begin (9600);
lcd.init ();
lcd.print (Version);
rtc.begin();
dallasRange.begin();
dallasRange.setResolution(TEMPERATURE_PRECISION);
for (int n = 0; n < Nbut; n++) {
pinMode (PinButs [n], INPUT_PULLUP);
butState [n] = digitalRead (PinButs [n]);
}
heating (pR, 1);
}
RESET
UP
AIRGUN
CLUB
RANGE
AIRGUN
RANGE
CLUB
SELECT
ENTER
RIGHT
DOWN
BOILER
DS3821
FITTED
HEARTBEAT
Uses the internal pullup resistors for the button inputs