Instantly share code, notes, and snippets.
Created
June 24, 2011 12:33
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
Save monsonite/1044680 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* MEGA MEGA MEGA MEGA MEGA MEGA MEGA MEGA MEGA MEGA MEGA MEGA MEGA MEGA MEGA MEGA*/ | |
/*********************************************************************************** | |
/****************Navitrino Solar/Heating Controller********************************* | |
/*********************************************************************************** | |
// ---------------navitrino1_53_M - Changes since last version:-------------------- | |
Updated Mon 20/12/10 | |
Accumulates gas pulse count (10 litres) over hourly intervals to allow mean hourly power to be displayed | |
Displays value for last hour 60 consecutive outputs allowing easy bar-graphing in XL | |
Multiply hourly count by 39/360 to get mean power in kWh | |
Updated Sat 4/12/10 | |
Now measures 2 room temeperatures (temp1 workroom, temp5 livingroom) | |
Takes average temperature and uses this for temp contol | |
Updates on Sat 20/11/10 | |
Ported across to Arduino Mega 2560 | |
Weekend daytime temp increased to 19C | |
Day start now 7am | |
Boost control lowered to 22C on potentiometer | |
updates on Sunday 14th November | |
Relay board software serial (pin 7) added to boilercontrol() | |
Sends "R1" for CH relay, "R2" for HW relay, "R3" for both relays, "R0" for no relays | |
Extra code added to catch case where temperature lies within hysteresis band and send boiler off | |
updated on Wednesday 10th November 2010 | |
This version uses DS1302 Real Time Clock | |
RF Transmitter module Tx pin is now on Digital 9 (moved from Digital 10) | |
Boilerstate is now used to control a LED on Digital 7 | |
//---------------------------------------------------------------------------------- | |
26th June 2010 - 7th Nov 2010 | |
Ken Boak Arbour Wood Ltd. | |
This version for standard Arduino with NuElectronics Sensor Shield Oct 2010 | |
Implements simple heating controller using wireless Boiler On / Boiler Off Packets | |
ADC 0 Outside Temperature 20K thermistor | |
ADC 1 Light Level | |
ADC 2 Set point Potentiometer 24C max | |
ADC 3 Tank Outlet | |
ADC 4 Tank Entry | |
ADC 5 Room Temperature | |
Simple Time and Temperature display using the ModernDevice's LCD117 Controller | |
This sketch reads up to 6 10K thermistors, performs linearisation and conversion to degrees C. | |
It displays the temperatures on a 4 line x 20 character LCD display | |
A domestic controller board based on the Arduino and Nano ATmega328 microcontroller boards | |
Intended to replace/augment existing domestic heating controllers and provide datalogging capability | |
Uses: | |
1. Solar Water Heating Controller - simple control with circulation pump relay | |
2. Central Heating / woodburner controller - determines best usage of hot water | |
3. Electricity Monitor - whole house electricity consumption | |
4. Gas consumption monitor - pulse counter on optical sensor on gas meter | |
5. pV / battery charge controller/datalogger | |
6. Gasifier controller | |
7. CHP controller - engine start/stop, rpm, voltage monitor etc | |
8. Battery management system for wind or solar pV. | |
9. General purpose control tasks | |
10. Temperature, climate and weather monitoring and datalogging. | |
The controller is based on the ATmega 328 microcontroller with 32K program space | |
and is programmed using the popular Arduino C based language. | |
The basic Arduino is augmented with an SDcard interface for data storage and a real time clock | |
using the Dallas 130X range of battery backed RTC chips. This functionality can be added to an | |
existing Arduino using the NuElectronics Real Time Datalog and I/O shield. | |
LDR sensor has 10K resistor to 0V. | |
Dark value < 100 | |
Daylight indoors ~ 800 | |
Desk lamp ~ 900 | |
Light level Sensor connected to ADC3 | |
Setpoint control potentiometer on ADC 2 | |
Room Temp Thermistor on ADC4 | |
Hot Water Tank Temp Thermistor on ADC5 | |
433MHz Tx Module | |
Digital 11 Tx Data | |
Digital 12 Tx +5V power | |
Digital 13 LE | |
// Pseudo Code | |
Update time | |
Read and average the ADC channels | |
Make decision on whether boiler on based on time and temperature | |
Calculate heat gain/heat lost | |
Update display according to which mode | |
Accumulate the readings from the ADCs 64 times into unsigned int | |
Then divide by 64 to get average | |
Then put averaged reading through the thermistor linearisation code | |
*/ | |
//----------------------------------------------------------------------------------- | |
// Libraries | |
//----------------------------------------------------------------------------------- | |
#include <DS1302.h> | |
#include <SoftwareSerial.h> | |
#include <math.h> | |
#include <Timer.h> | |
#include "etherShield.h" | |
Timer RTOS = Timer(); | |
timer_h rep; | |
// Init the DS1302 | |
DS1302 rtc(6, 4, 3); | |
//****************************************************************************************** | |
//----------------------------------------------------------------------------------- | |
// Variables | |
//----------------------------------------------------------------------------------- | |
unsigned long time_x ; | |
// 00010203040506070809101112 | |
/* | |
long monday_am = B00000000000000000000000000000000 ; | |
long tuesday_am = B00000000000000000000000000000000 ; | |
long wednesday_am = B00000000000000000000000000000000 ; | |
long thursday_am = B00000000000000000000000000000000 ; | |
long friday_am = B00000000000000000000000000000000 ; | |
long saturday_am = B00000000000000000000000000000000 ; | |
long sunday_am = B00000000000000000000000000000000 ; | |
long monday_pm = B00000000000000000000000000000000 ; | |
long tuesday_pm = B00000000000000000000000000000000 ; | |
long wednesday_pm = B00000000000000000000000000000000 ; | |
long thursday_pm = B00000000000000000000000000000000 ; | |
long friday_pm = B00000000000000000000000000000000 ; | |
long saturday_pm = B00000000000000000000000000000000 ; | |
long sunday_pm = B00000000000000000000000000000000 ; | |
*/ | |
#define Therm0 0 // Analog Pin 0 | |
#define Therm1 1 // Analog Pin 1 | |
#define Therm2 2 // Analog Pin 2 | |
#define Therm3 3 // Analog Pin 3 | |
#define Therm4 4 // Analog Pin 4 | |
#define Therm5 5 // Analog Pin 5 | |
#define LDR 4 | |
unsigned int acc0; // Accumulator for ADC0 64 readings | |
unsigned int acc1; // Accumulator for ADC1 64 readings | |
unsigned int acc2; // Accumulator for ADC2 64 readings | |
unsigned int acc3; // Accumulator for ADC3 64 readings | |
unsigned int acc4; // Accumulator for ADC4 64 readings | |
unsigned int acc5; // Accumulator for ADC5 64 readings | |
double temp; | |
double temp0; // storage for temperature readings from sensors | |
double temp1; | |
double temp2; | |
double temp3; | |
double temp4; | |
double temp5; | |
double tav; // average temperature | |
double tless; // lower of room temperatures | |
double deltaT; | |
double mtemp0; // storage for averaged minute temperature readings from sensors | |
double mtemp1; | |
double mtemp2; | |
double mtemp3; | |
double mtemp4; | |
double mtemp5; | |
double acctemp0; // accumulated temperature readings from sensors | |
double acctemp1; | |
double acctemp2; | |
double acctemp3; | |
double acctemp4; | |
double acctemp5; | |
double set_temp; | |
double ten_temp; //ten times room tempertaure | |
double ten_set; //ten times set tempertaure | |
int adc0; | |
int adc1; | |
int adc2; | |
int adc3; | |
int adc4; | |
int adc5; | |
int illum; | |
char N; | |
int I; | |
int ByteVar; | |
int x; | |
int hours; | |
int mins; | |
int secs; | |
int night_close = 24; // Closedown 12am | |
int night_am = 1; | |
int morn_open = 7; // Day start 7am | |
int evening_start = 16; // Evening start = 16:00 | |
int day_temp = 17; // default temperatures | |
int eve_temp = 19; | |
int night_temp = 17; | |
int min_count = 0; | |
int hour_pulse_count = 0; | |
int pulse_count = 0 ; | |
int day = 0; | |
int eve = 0; | |
int night = 0; | |
int cold = 3; // Temperatures to make thresholding decisions around | |
int mild = 8; | |
int warm = 12; | |
int cool = 40; | |
int hot = 45; | |
unsigned long secs_now; | |
unsigned long secs_old; | |
unsigned long millis_old = 0; | |
unsigned long start_time; | |
unsigned long end_time; | |
unsigned long print_time = 0; | |
unsigned long update_time = 0; | |
unsigned long gas_count; | |
unsigned long gas_total; | |
unsigned long start_count = 925368; | |
unsigned long Counter1 = 0; | |
unsigned long Counter2 = 0; | |
unsigned long ct_1 = 0; | |
unsigned long ct_2 = 0; | |
unsigned long pulse_on = 0; | |
unsigned long pulse_off = 0; | |
unsigned long gas = 0 ; // returmed pulse count for Gas channel | |
unsigned long elec ; // returned pulsecount for Electricity channel | |
int gas_old = 0; | |
int gas_now = 0; | |
int gas_diff = 0; | |
int boilerstate = 0; | |
int waterstate = 0; | |
int val = 0; // variable to store the read value | |
int Tx_bytes[] = {170,172,89,153,89,85}; // An array of 6 bytes that are sent to the Tx | |
int _bitPeriod = 1000000 / 2000; // define the RF Tx serial baudrate in microseconds | |
int mode = 0 ; // Defines the Screen Mode and what parameters are displayed | |
char tod_str[] = "night"; // 6 character string for Time of Day (tod_str) | |
int on_count = 0; | |
int off_count = 0; | |
int state_now; | |
int state_old; | |
//----------------------------------------------------------------------------------- | |
// Connections | |
//----------------------------------------------------------------------------------- | |
int pulse_0_pin = 2; // pulse counter 0 on pin 2 | |
// int pulse_1_pin = 3; // pulse counter 1 on pin 3 | |
// int _receivePin = 3; | |
int CH_relay = 7; // Central Heating Relay connected to digital 7 | |
int txPin = 8; // Use pin 8 for software serial to display | |
int HW_relay = 7; // Hot Water Relay connected to digital pin 9 | |
int _transmitPin = 9; // define the Tx serial output pin | |
int LEDPin = 7; // LED connected to digital pin 7 - on when boiler on | |
int rxPin = 3; // rxPin is immaterial - not used - just make this an unused Arduino pin number | |
int relay_tx = 7; // relay board is controlled by serial on pin 7 | |
int relay_data; | |
SoftwareSerial LCDserial = SoftwareSerial(rxPin, txPin); // software serial link to LCD | |
SoftwareSerial relay_board_serial = SoftwareSerial(rxPin, relay_tx); // software serial link to relay board | |
// LCDserial is connected to the TX pin so LCDserial.print commands are used | |
//****************************************************************************************** | |
// Init a Time-data structure | |
Time t; | |
//----------------------------------------------------------------------------------- | |
// Setup | |
//----------------------------------------------------------------------------------- | |
void setup() | |
{ | |
// Set the clock to run-mode, and disable the write protection | |
rtc.halt(false); | |
rtc.writeProtect(false); | |
// Setup Serial connections | |
Serial.begin(9600); | |
relay_board_serial.begin(9600); // begin the 9600baud serial link to the relay board | |
// The following lines can be commented out to use the values already stored in the DS1302 | |
rtc.setTime(9,10,00); // Set the time to 9:30:00 (24hr format) | |
delay(100); | |
rtc.setDOW(TUESDAY); // Set Day-of-Week to FRIDAY | |
delay(100); | |
rtc.setDate(26, 4, 2011); // Set the date to Nov 6th, 2010 | |
delay(100); | |
t = rtc.getTime(); // Get the real time and initialise the hours, mins and secs variables | |
hours = (t.hour); | |
mins = (t.min); | |
secs = (t.sec); | |
//---------------------------------------------------------------------------------- | |
// Set up the I/O pins and attache interrupt for pulse counter(s) | |
pinMode(pulse_0_pin,INPUT); | |
pinMode(CH_relay,OUTPUT); | |
pinMode(HW_relay,OUTPUT); | |
pinMode(LEDPin, OUTPUT); | |
// pinMode(pulse_1_pin,INPUT); | |
pinMode(_transmitPin, OUTPUT); // define the tx pin as output | |
// pinMode(_receivePin, INPUT); // define the receivePin as input | |
attachInterrupt(0, increaseCounter1, RISING); // set up the interrupts on INT0 and INT1 (digital 2 & 3) | |
// attachInterrupt(1, increaseCounter2, RISING); | |
lcd_init(); // Initialise the LCD | |
//--------------------------------------------------------------------------------------- | |
// Now set up the RTOS task scheduler | |
//--------------------------------------------------------------------------------------- | |
RTOS.once(1, t_once); // t_once is performed only once - such as display initialisation/ banner screen etc | |
RTOS.repeat(1, t_sec); // t_sec is the task we do once per second | |
RTOS.repeat(15, t_15); | |
RTOS.repeat(60, t_60); // t_60 is the task we do every 60 secs | |
// rep = RTOS.repeat(10, t_rep); | |
// RTOS.repeat(2, t_2); | |
// RTOS.repeat(3, t_3); | |
// RTOS.repeat(10, t_10); | |
} // End of setup code | |
//************************************************************************************************** | |
// Once Only Tasks | |
//************************************************************************************************** | |
void t_once(void) { | |
Serial.print("Navitrino "); // Print Navitrino to terminal plus time, day of week and date strings | |
Serial.print(rtc.getTimeStr()); | |
Serial.print(" "); | |
// Send Day-of-Week | |
Serial.print(rtc.getDOWStr()); | |
Serial.print(" "); | |
// Send date | |
Serial.print(rtc.getDateStr()); | |
Serial.println(""); | |
// RTOS.destroy(rep); | |
} | |
//************************************************************************************************** | |
// Once Per Second Tasks | |
//************************************************************************************************** | |
void t_sec(void) { | |
get_ADCs(); // Read the ADC channels - average of 64 readings | |
convert_ADCs(); | |
time_update(); // Update the time on the LCD display | |
print_status(); // Update the temperature, heating and boilaer staus on LCD | |
// Serial.print(secs); | |
while (min_count <=59) | |
{ // Read the ADCs 60 times and average | |
acctemp0 = acctemp0 + temp0; | |
acctemp1 = acctemp1 + temp1; | |
acctemp2 = acctemp2 + temp2; | |
acctemp3 = acctemp3 + temp3; | |
acctemp4 = acctemp4 + temp4; | |
acctemp5 = acctemp5 + temp5; | |
min_count++; | |
} | |
if (min_count>=59)min_count==0; | |
// End of minute_av_temps() | |
} | |
//************************************************************************************************** | |
// Once Per 15 second Tasks | |
//************************************************************************************************** | |
void t_15(void) { | |
update_boiler(); // Check all the temps and times and turn boiler on or off | |
// Serial.println("Update Boiler"); | |
} | |
//************************************************************************************************** | |
// Once Per Minute Tasks | |
//************************************************************************************************** | |
void t_60(void) { | |
update_time = millis(); | |
t = rtc.getTime(); // get time from RTC and update hours, mins and secs | |
hours = (t.hour); | |
mins = (t.min); | |
secs = (t.sec); | |
if (mins == 0 ) { // once per hour update the hourly pulse count accumulation | |
hour_pulse_count = pulse_count; | |
pulse_count = 0; | |
} | |
/* | |
*/ | |
// Send time | |
Serial.print(rtc.getTimeStr()); | |
Serial.print(" "); | |
Serial.print(set_temp); | |
Serial.print(" "); | |
print_minute(); // Print the time etc to terminal once per minute | |
// print_Temps(); // Print out the temperature data | |
mtemp0 = acctemp0/60; // calcilate the minute average temperatures | |
mtemp1 = acctemp1/60; | |
mtemp2 = acctemp2/60; | |
mtemp3 = acctemp3/60; | |
mtemp4 = acctemp4/60; | |
mtemp5 = acctemp5/60; | |
/* | |
Serial.print(mtemp0); | |
Serial.print(" "); | |
Serial.print(mtemp1); | |
Serial.print(" "); | |
Serial.print(mtemp2); | |
Serial.print(" "); | |
Serial.print(mtemp3); | |
Serial.print(" "); | |
Serial.print(mtemp4); | |
Serial.print(" "); | |
Serial.print(mtemp5); | |
Serial.println(" "); | |
*/ | |
acctemp0 = 0; // Reset the acummulators for ADC totals | |
acctemp1 = 0; | |
acctemp2 = 0; | |
acctemp3 = 0; | |
acctemp4 = 0; | |
acctemp5 = 0; | |
} | |
//************************************************************************************************** | |
/* | |
void t_rep(void) { | |
time_x = millis(); | |
Serial.println(time_x); | |
} | |
void t_2(void) { | |
Serial.println("Timer_2"); | |
} | |
void t_3(void) { | |
Serial.println("Timer_3"); | |
} | |
void t_10(void) { | |
Serial.println("Timer_10"); | |
} | |
*/ | |
//************************************************************************************************** | |
// Main Loop | |
//************************************************************************************************** | |
// now for the main once per second loop | |
void loop() | |
{ /*nil*/ } | |
// End of main loop | |
// **************************************************************************************** | |
//----------------------------------------------------------------------------------- | |
// Functions | |
//----------------------------------------------------------------------------------- | |
//***************************Initialise LCD Display********************************** | |
void lcd_init(void) { | |
pinMode(txPin, OUTPUT); | |
LCDserial.begin(9600); // 9600 baud is chip comm speed | |
LCDserial.print("?G420"); // set display geometry, 4 x 20 characters in this case | |
delay(500); // pause to allow LCD EEPROM to program | |
LCDserial.print("?B80"); // set backlight to 80 hex, medium brightness | |
delay(1000); // pause to allow LCD EEPROM to program | |
LCDserial.print("?s6"); // set tabs to six spaces | |
delay(1000); // pause to allow LCD EEPROM to program | |
LCDserial.print("?D00000000000000000"); // define special characters | |
delay(300); // delay to allow write to EEPROM | |
// see moderndevice.com for a handy custom char generator (software app) | |
LCDserial.print("?f"); // clear the LCD | |
delay(10); | |
LCDserial.print("Initialising..."); | |
LCDserial.print("?c0"); // turn cursor off | |
delay(1000); | |
LCDserial.print("?x00?y0"); // cursor to first character of line 0 | |
LCDserial.print("Navitrino Controller"); | |
delay(100); | |
LCDserial.print("?x00?y1"); // move cursor to beginning of line 1 | |
LCDserial.print("Arbour Wood Ltd"); // crass commercial message | |
delay(1000); // pause 1 sec to admire | |
LCDserial.print("?x00?y2"); // move cursor to beginning of line 0 | |
LCDserial.print("Time Temp Display"); // displys LCD #117 on the screen | |
LCDserial.print("?x00?y3"); // cursor to first character of line 1 | |
LCDserial.print("powercubes.com"); | |
delay(1000); // pause 1 sec to admire | |
LCDserial.print("?f"); // clear the screen | |
LCDserial.print("?x00?y0"); // cursor to first character of line 0 | |
LCDserial.print("Time"); | |
delay(100); | |
LCDserial.print("?x00?y1"); // move cursor to beginning of line 1 | |
LCDserial.print("T1"); // T1 message | |
delay(100); | |
LCDserial.print("?x00?y2"); // move cursor to beginning of line 2 | |
LCDserial.print("T2"); // displys LCD #117 on the screen | |
delay(100); | |
LCDserial.print("?x00?y3"); // cursor to first character of line 3 | |
LCDserial.print("T3"); | |
} | |
//************************************************************************************* | |
void print_minute() { | |
// ******************************************************************************** | |
// read the values from the pulse counters and temperature sensors and print out once per minute | |
// ********************************************************************************* | |
gas = returnCounter1(ct_1); // get the two pulse figures x = gas, y = electricity | |
gas_total = gas + start_count; | |
// gas_count = start_count + returnCounter2(ct_2); | |
// display_time(); | |
// Serial.print(" "); | |
// Serial.print(millis()); | |
// Serial.print(" "); | |
Serial.print(gas); | |
Serial.print(" "); | |
Serial.print(gas_total); | |
Serial.print(" "); | |
// Serial.print(gas_count); | |
// Serial.print(" "); | |
gas_now = gas; // Calculate and display the number of gas pulses received in the last minute | |
gas_diff = gas_now - gas_old; | |
gas_old = gas_now; | |
print_Temps(); // Print out the temperature data | |
} | |
//************************************************************************************************************ | |
// Check the time of day and the required temperature and turn on boiler if needed | |
//************************************************************************************************************ | |
// This is the main decision making part of the program | |
// Get the day of the week from RTC as t.dow where Monday = 1, Sunday = 7 | |
// If t.dow >= 4 is Thursday, Friday, Saturday, Sunday | |
// If t.dow >= 6 is Saturday, Sunday i.e. weekend | |
// If 00 <= hours <= 7 i.e. night-time maintain temperature at minimum of 17C night_temp | |
// If 8 <= hours <= 16 i.e. daytime maintain temperature at minimum of 17C day_temp | |
// If 17 <= hours <= 24 i.e. evening maintain temperature at minimum of 19C night_temp | |
// First look at the time and see if we are day, evening or night | |
void update_boiler() { | |
// digitalWrite(CH_relay, HIGH); | |
// digitalWrite(CH_relay, LOW); | |
//--------------------------------------------------------------------------------------- | |
// First determine whether day, evening or night | |
if (hours >= night_am && hours <= morn_open ) { // Night-time idle period | |
night = HIGH; | |
day = LOW; | |
eve = LOW; | |
set_temp = temp2; // Idle at pot value | |
} | |
else if (hours >= morn_open && hours <= evening_start) { // Day-time idle period | |
night = LOW; | |
day = HIGH; | |
eve = LOW; | |
set_temp = temp2; // Idle at pot value | |
} | |
else if (hours >= evening_start && hours <= night_close ) { // Day-time idle period | |
night = LOW; | |
day = LOW; | |
eve = HIGH; | |
set_temp = temp2; // Idle at pot value in eveningtime | |
} | |
/* | |
//--------------------------------------------------------------------------------------- | |
// Now if Thurs, Fri,Sat, Sun increase the day temperature to 18C | |
if (t.dow >=4) { | |
if (night) { // Night-time idle period | |
set_temp = 17; // Idle at 17C overnight | |
} | |
else if (day) { // Day-time idle period | |
set_temp = 19; // Idle at 19C weekend daytime | |
} | |
else if (eve) { // Day-time idle period | |
set_temp = temp2; // Idle at pot value in eveningtime | |
} | |
} | |
*/ | |
//-------------------------------------------------------------------------------------- | |
// We now know whether day, evening or night and we have a set-temp | |
// Multiply room temp and set temp by 10 to give 1 decimal place accuracy | |
// From the set temp and the watertemp decide whether we need hot water and/or central heating | |
// Decide the boilerstate and watertate and then execute boiler_control() | |
deltaT = temp5 - temp0; // Calculate the temperature difference between inside and outside | |
set_temp = temp2; // Idle at pot value | |
tav = (temp1 * 10 + temp5 * 10)/20; | |
if (temp5 >= temp1) | |
{ | |
tless == temp1; | |
} | |
if (temp1 >= temp5) | |
{ | |
tless == temp5; | |
} | |
ten_temp = temp5 * 10; // ten times living room temperature | |
// ten_temp = tav * 10; // ten times average temperature | |
ten_set = set_temp * 10; | |
if (ten_temp <= (ten_set -2)) { // put in + 0.2 degrees hysteresis | |
boilerstate = HIGH; // Boiler On | |
LCDserial.print("?x10?y1"); // move cursor to beginning of xpos,ypos | |
LCDserial.print("On "); | |
// boiler_control(); // Send control packet to boiler | |
} | |
if (ten_temp >= (ten_set +2)) { // put in - 0.2 degrees hysteresis | |
boilerstate = LOW; // Boiler Off | |
LCDserial.print("?x10?y1"); // move cursor to beginning of xpos,ypos | |
LCDserial.print("Off"); | |
// boiler_control(); // Send control packet to boiler | |
} | |
/* | |
if (ten_temp >= (ten_set -2) && ten_temp <= (ten_set +2)); // test if set temp is within hysteresis band | |
{ | |
boilerstate = LOW; // Boiler Off | |
LCDserial.print("?x10?y1"); // move cursor to beginning of xpos,ypos | |
LCDserial.print("Set "); | |
// boiler_control(); // Send control packet to boiler | |
} | |
if (temp5 >= 22) { // Boost demanded on pot control | |
boilerstate = HIGH; // Boiler On | |
LCDserial.print("?x10?y1"); // move cursor to beginning of xpos,ypos | |
LCDserial.print("Boost "); | |
// boiler_control(); // Send control packet to boiler | |
} | |
// Now check if its 4am and whether its cold outside and a weekday - override temp stat and turn boiler on for 1 hour | |
if ((t.dow <=5) && (hours == 4) && (temp0 <= cold) ) { // Boiler on at 4am for 1 hour on cold mornings | |
boilerstate = HIGH; // Boiler On early to compensate for cold weather | |
LCDserial.print("?x10?y1"); // move cursor to beginning of xpos,ypos | |
LCDserial.print("On "); | |
// boiler_control(); | |
} | |
if ((t.dow <=5) && (hours == 5) && (temp0 <= cold) ) { // Keep Boiler on at 5am for 1 hour on cold mornings | |
boilerstate = HIGH; // Boiler On early to compensate for cold weather | |
LCDserial.print("?x10?y1"); // move cursor to beginning of xpos,ypos | |
LCDserial.print("On "); | |
// boiler_control(); | |
} | |
if ((t.dow <=5) && (hours == 4) && (temp3 <= cool) ) { // If 4am, weekday and water temp is cool - bring on HW | |
boilerstate = HIGH; // Boiler On early to compensate for cold weather | |
waterstate = HIGH; // turn on HW valve relay | |
LCDserial.print("?x10?y1"); // move cursor to beginning of xpos,ypos | |
LCDserial.print("On "); | |
// boiler_control(); | |
} | |
else if ((t.dow <=5) && (hours == 4) && (temp3 >= hot) ) { // If 4am, weekday and water temp is hot - hold off HW | |
boilerstate = LOW; // Boiler On early to compensate for cold weather | |
waterstate = LOW; // turn off HW valve relay | |
LCDserial.print("?x10?y1"); // move cursor to beginning of xpos,ypos | |
LCDserial.print("Off "); | |
// boiler_control(); | |
} | |
if ((t.dow <=5) && (hours >= 4) && (temp3 >= hot) && (ten_temp >= ten_set) ) { // If after 4am, weekday and water temp is hot - hold off HW | |
boilerstate = LOW; // Boiler On early to compensate for cold weather | |
waterstate = LOW; // turn off HW valve relay | |
LCDserial.print("?x10?y1"); // move cursor to beginning of xpos,ypos | |
LCDserial.print("Off "); | |
// boiler_control(); | |
} | |
*/ | |
boiler_control(); // send command to boiler and set CH and HW relays | |
} // End of update_boiler() | |
//****************************************************************************************** | |
// boiler_control() | |
// Outputs a wireless packet (2000 baud) to control a Drayton Digistat wireles thermostat receiver | |
// Boiler Off packet AA AC 59 99 59 55 59 56 AA | |
// Boiler On packet AA AC 59 99 59 55 95 65 AA | |
// read MSB first from left to right | |
// Uses function RF_tx to put 8 bit serial on digital output pin 2 (no start or stop bits) | |
// If boilerstate == HIGH then boiler on | |
// If boilerstate == LOW then boiler off | |
//******************************************************************************************** | |
void boiler_control() { | |
// digitalWrite(LEDPin,boilerstate); // Echo the boilerstate on the LED | |
// digitalWrite(HW_relay,waterstate); // Turn on the HW if needed | |
relay_data = 0; | |
if (boilerstate==HIGH) { // boiler relay is bit 0 | |
relay_data = 1; | |
} | |
if (waterstate==HIGH) { | |
relay_data = relay_data + 2; // hot water relay is bit 1 | |
} | |
relay_board_serial.print("R"); | |
relay_board_serial.print(relay_data); // send relay control byte | |
relay_board_serial.print("\r"); // carriage return | |
int i; | |
for (i=0; i<6; i++) { // Output the common part of the packet 6 bytes | |
RF_tx(Tx_bytes[i]); | |
} | |
if(boilerstate==HIGH) { | |
RF_tx(149); // Turn the boiler on | |
RF_tx(101); | |
RF_tx(170); | |
} | |
else { | |
RF_tx(89); // Turn the boiler off | |
RF_tx(86); | |
RF_tx(170); | |
} | |
} // end of boiler_control() | |
//************************************************************************************************** | |
// RF_tx - sends the serial packet to the transmitPin | |
void RF_tx(uint8_t b) | |
{ | |
int bitDelay = _bitPeriod - clockCyclesToMicroseconds(50); // a digitalWrite is about 50 cycles | |
byte mask; | |
for (mask = B10000000; mask; mask >>= 1) { | |
if (b & mask){ // choose bit | |
digitalWrite(_transmitPin,HIGH); // send 1 | |
} | |
else{ | |
digitalWrite(_transmitPin,LOW); // send 0 | |
} | |
delayMicroseconds(bitDelay); | |
} | |
} // End of RF_tx | |
//*********************************************************************************************** | |
//***************************************************************************************************** | |
// Thermistor Linearisation and temperature print-out code | |
// Thermistor Linearisation Code | |
double Thermistor(int RawADC) { | |
// Inputs ADC Value from Thermistor and outputs Temperature in Celsius | |
// requires: include <math.h> | |
// Utilizes the Steinhart-Hart Thermistor Equation: | |
// Temperature in Kelvin = 1 / {A + B[ln(R)] + C[ln(R)]^3} | |
// where A = 0.001129148, B = 0.000234125 and C = 8.76741E-08 | |
long Resistance; double Temp; // Dual-Purpose variable to save space. | |
Resistance=((10240000/RawADC) - 10000); // Assuming a 10k Thermistor. Calculation is actually: Resistance = (1024 * BalanceResistor/ADC) - BalanceResistor | |
Temp = log(Resistance); // Saving the Log(resistance) so not to calculate it 4 times later. // "Temp" means "Temporary" on this line. | |
Temp = 1 / (0.001129148 + (0.000234125 * Temp) + (0.0000000876741 * Temp * Temp * Temp)); // Now it means both "Temporary" and "Temperature" | |
Temp = Temp - 273.15; // Convert Kelvin to Celsius // Now it only means "Temperature" | |
/* | |
// BEGIN- Remove these lines for the function not to display anything | |
Serial.print("ADC: "); Serial.print(RawADC); Serial.print("/1024"); // Print out RAW ADC Number | |
Serial.print(", Volts: "); printDouble(((RawADC*4.860)/1024.0),3); // 4.860 volts is what my USB Port outputs. | |
Serial.print(", Resistance: "); Serial.print(Resistance); Serial.print("ohms"); | |
// END- Remove these lines for the function not to display anything | |
*/ | |
// Uncomment this line for the function to return Fahrenheit instead. | |
//Temp = (Temp * 9.0)/ 5.0 + 32.0; // Convert to Fahrenheit | |
return Temp; // Return the Temperature | |
} | |
//***************************************************************************************************** | |
void printDouble(double val, byte precision) { | |
// prints val with number of decimal places determine by precision | |
// precision is a number from 0 to 6 indicating the desired decimal places | |
// example: printDouble(3.1415, 2); // prints 3.14 (two decimal places) | |
Serial.print (int(val)); //prints the int part | |
if( precision > 0) { | |
Serial.print("."); // print the decimal point | |
unsigned long frac, mult = 1; | |
byte padding = precision -1; | |
while(precision--) mult *=10; | |
if(val >= 0) frac = (val - int(val)) * mult; else frac = (int(val) - val) * mult; | |
unsigned long frac1 = frac; | |
while(frac1 /= 10) padding--; | |
while(padding--) Serial.print("0"); | |
Serial.print(frac,DEC) ; | |
} | |
} | |
//***************************************************************************************************** | |
void LCDprintDouble(double val, byte precision) { | |
// prints val with number of decimal places determine by precision on the LCD | |
// precision is a number from 0 to 6 indicating the desired decimal places | |
// example: printDouble(3.1415, 2); // prints 3.14 (two decimal places) | |
// Prints at line xpos, column ypos | |
LCDserial.print (int(val)); //prints the int part | |
if( precision > 0) { | |
LCDserial.print("."); // print the decimal point | |
unsigned long frac, mult = 1; | |
byte padding = precision -1; | |
while(precision--) mult *=10; | |
if(val >= 0) frac = (val - int(val)) * mult; else frac = (int(val) - val) * mult; | |
unsigned long frac1 = frac; | |
while(frac1 /= 10) padding--; | |
while(padding--) LCDserial.print("0"); | |
LCDserial.print(frac,DEC) ; | |
} | |
} | |
//***************************************************************************************************** | |
//************************************************************************************************************************* | |
// Get the average of 64 ADC readings | |
//************************************************************************************************************************* | |
void get_ADCs() { | |
acc0 = 0; // Reset the acummulators for ADC totals | |
acc1 = 0; | |
acc2 = 0; | |
acc3 = 0; | |
acc4 = 0; | |
acc5 = 0; | |
for ( int i = 0; i<=63; i++) { // Read the ADCs 64 times and average | |
acc0 = acc0 + analogRead(Therm0); | |
acc1 = acc1 + analogRead(Therm1); | |
acc2 = acc2 + analogRead(Therm2); | |
acc3 = acc3 + analogRead(Therm3); | |
acc4 = acc4 + analogRead(Therm4); | |
acc5 = acc5 + analogRead(Therm5); | |
} | |
adc0 = acc0/64; // scale back down | |
adc1 = acc1/64; | |
adc2 = acc2/64; | |
adc3 = acc3/64; | |
adc4 = acc4/64; | |
adc5 = acc5/64; | |
} // End of get_ADCs() | |
//**************************************************************************************************** | |
// Convert the averaged ADC Readings to Centigrade | |
//**************************************************************************************************** | |
void convert_ADCs() { // Take the averaged ADC readings and convert to degrees centigrade | |
temp0 = Thermistor(adc0); | |
temp1 = Thermistor(adc1); | |
temp2 = Thermistor(adc2); | |
temp3 = Thermistor(adc3); | |
temp4 = Thermistor(adc4); | |
temp5 = Thermistor(adc5); | |
} | |
//*********************************************************************************************** | |
// Print out the temperature readings to serial terminal | |
//*********************************************************************************************** | |
void print_Temps(){ // Print out the temperature readings to serial terminal | |
Serial.print(temp0); // outside temp | |
Serial.print(", "); | |
Serial.print(temp5); // room temp :- lounge | |
Serial.print(", "); | |
Serial.print(temp1); // room temp :- bed | |
Serial.print(", "); | |
Serial.print(deltaT); // delta temp | |
Serial.print(", "); | |
Serial.print(temp3); // tank temp | |
Serial.print(", "); | |
Serial.print(temp4); // flow temp | |
Serial.print(", "); | |
Serial.print(boilerstate); // boiler on or off | |
Serial.print(", "); | |
Serial.print(waterstate); // hot water on or off | |
Serial.print(", "); | |
if (boilerstate) Serial.print("On"); // Print whether boiler is On or Off | |
if (!boilerstate) Serial.print("Off"); | |
Serial.print(", "); | |
// Now calculate the duty cycle - wait for a change in boilerstate and count the on times and the off times | |
state_now = boilerstate; | |
if (state_now == HIGH && state_old == LOW) { // entered a heating on period | |
off_count = 0; | |
on_count = on_count + 1; | |
} | |
if (state_now == HIGH && state_old == HIGH) { // still in a heating on period | |
off_count = 0; | |
on_count = on_count + 1; | |
} | |
if (state_now == LOW && state_old == HIGH) { // entered a heating off period | |
off_count = off_count + 1; | |
on_count = 0 ; | |
} | |
if (state_now == LOW && state_old == LOW ) { // entered a heating off period | |
off_count = off_count + 1; | |
on_count = 0 ; | |
} | |
state_old = state_now; | |
Serial.print(on_count); // hot water on or off | |
Serial.print(", "); | |
Serial.print(off_count); // hot water on or off | |
Serial.print(", "); | |
Serial.print(hour_pulse_count); | |
Serial.print(", "); | |
Serial.print(pulse_count); | |
Serial.print(", "); | |
Serial.print(gas_diff); | |
Serial.print(", "); | |
if (night) { // Night-time idle period | |
Serial.println("Night"); | |
} | |
else if (day) { // Day-time idle period | |
Serial.println("Day"); | |
} | |
else if (eve) { // Day-time idle period | |
Serial.println("Evening"); | |
} | |
} // End of print_Temps() | |
//******************************************************************************* | |
// Print out the time in HH:MM:SS format with leading zeros where applicable | |
void display_time() { | |
if (hours < 10) | |
{ | |
Serial.print("0"); // print leading zero | |
Serial.print(hours); // display hours | |
} | |
else { | |
Serial.print(hours); // display hours | |
} | |
Serial.print(":"); // print colon | |
if (mins < 10) | |
{ | |
Serial.print("0"); // print leading zero | |
Serial.print(mins); | |
} | |
else { | |
Serial.print(mins); | |
} | |
Serial.print(":"); // print colon | |
if (secs < 10) | |
{ | |
Serial.print("0"); | |
// print leading zero | |
Serial.print(secs); | |
} | |
else { | |
Serial.print(secs); | |
} | |
} | |
// ****************************************************************************************** | |
// Interrupt Service Routine | |
// ****************************************************************************************** | |
void increaseCounter1() // Interupt Sservice Routines - update the two counters | |
{ | |
Counter1++; | |
pulse_count++; // increment the hourly total register | |
} | |
unsigned long returnCounter1(unsigned long ct_1) // return the counts ct_1 and ct_2 to the main loop | |
{ | |
{ | |
uint8_t SaveSREG = SREG; // save interrupt flag | |
noInterrupts(); // disable interrupts | |
ct_1 = Counter1; // access the shared data | |
// Counter1 = 0; // reset Counter1 to 0 | |
SREG = SaveSREG; // restore the interrupt flag | |
} | |
return ct_1 ; | |
} | |
// Second interrupt pulsecounter - not used when RTC is used | |
/* | |
void increaseCounter2() | |
{ | |
Counter2++; | |
} | |
unsigned long returnCounter2(unsigned long ct_2) | |
{ | |
{ | |
uint8_t SaveSREG = SREG; // save interrupt flag | |
noInterrupts(); // disable interrupts | |
ct_2 = Counter2; // access the counter | |
// Counter2 = 0; // reset Counter2 to 0 | |
SREG = SaveSREG; // restore the interrupt flag | |
} | |
return ct_2; | |
} | |
*/ | |
//******************************************************************************************************************************* | |
// Update Time on LCD display | |
//******************************************************************************************************************************* | |
void time_update() | |
{ | |
LCDserial.print("?x10?y0"); // move cursor to col 10 of line 1 | |
LCDserial.print(" : : "); // clear time display | |
// Increment the seconds and update the hours, mins and secs variables | |
// secs ++ ; | |
/* Old code for incrementing hh:mm:ss superceded by RTC | |
if (secs > 59) | |
{ | |
secs = 0; | |
mins ++; | |
// print_minute(); // Print the time etc to terminal once per minute | |
} | |
if (mins > 59) | |
{ | |
mins = 0; | |
hours ++; | |
} | |
if (hours > 23) | |
{ | |
hours = 0; | |
} | |
*/ | |
t = rtc.getTime(); // get the hours, mins and secs from RTC | |
hours = (t.hour); | |
mins = (t.min); | |
secs = (t.sec); | |
// Now format the hours minutes and seconds with any leading zeros for printing to LCD and terminal | |
if (hours < 10) | |
{ | |
LCDserial.print("?x10?y0"); // move cursor to beginning of line 1 | |
LCDserial.print("0"); // print leading zero | |
// Serial.print("0"); // print leading zero | |
LCDserial.print("?x11?y0"); // move cursor to beginning of line 1 | |
LCDserial.print(hours); // display hours | |
// Serial.print(hours); // display hours | |
} | |
else { | |
LCDserial.print("?x10?y0"); // move cursor to beginning of line 1 | |
LCDserial.print(hours); // display hours | |
// Serial.print(hours); // display hours | |
} | |
LCDserial.print("?x12?y0"); // move cursor to beginning of line 1 | |
LCDserial.print(":"); // display colon | |
// Serial.print(":"); // print colon | |
if (mins < 10) | |
{ | |
LCDserial.print("?x13?y0"); // move cursor to beginning of line 1 | |
LCDserial.print("0"); // print leading zero | |
// Serial.print("0"); // print leading zero | |
LCDserial.print("?x14?y0"); // move cursor to beginning of line 1 | |
LCDserial.print(mins); // display mins | |
// Serial.print(mins); | |
} | |
else { | |
LCDserial.print("?x13?y0"); // move cursor to beginning of line 1 | |
LCDserial.print(mins); // display mins | |
// Serial.print(mins); | |
} | |
LCDserial.print("?x15?y0"); // move cursor to beginning of line 1 | |
LCDserial.print(":"); // display colon | |
// Serial.print(":"); // print colon | |
if (secs < 10) | |
{ | |
LCDserial.print("?x16?y0"); // move cursor to beginning of line 1 | |
LCDserial.print("0"); // print leading zero | |
// Serial.print("0"); | |
// print leading zero | |
LCDserial.print("?x17?y0"); // move cursor to beginning of line 1 | |
LCDserial.print(secs); // display secs | |
// Serial.print(secs); | |
} | |
else { | |
LCDserial.print("?x16?y0"); // move cursor to beginning of line 1 | |
LCDserial.print(secs); // display secs | |
// Serial.print(secs); | |
} | |
} | |
//********************************************************************************************************** | |
// Print out the Boiler, Temperature and Water Status to LCD in friendly format | |
// temp0 Outside Temperature | |
// temp1 Spare - or used for 1 wire network | |
// temp2 Set Temp | |
// temp3 Hot Water Temp | |
// temp4 Boiler Flow Temperature | |
// temp5 Room Temperature | |
//********************************************************************************************************** | |
void print_status() { | |
LCDserial.print("?x00?y0"); // move cursor to beginning of line 0 | |
LCDserial.print("Set "); | |
// temp=Thermistor(analogRead(Therm2)); // read ADC 2 (Setpoint) and convert it to Celsius | |
// temp2=temp; // temp2 = Setpoint temperature | |
LCDserial.print("?x4?y0"); // move cursor to beginning of xpos,ypos | |
LCDprintDouble(temp2,2); // display Celsius on the LCD display to 2 dp | |
LCDserial.print("?x00?y1"); // move cursor to beginning of line 1 | |
LCDserial.print("Heating "); | |
LCDserial.print("?x14?y1"); // move cursor to beginning of xpos,ypos | |
LCDserial.print(gas_total); // print out the gas meter total pulse count | |
LCDserial.print("?x00?y2"); // move cursor to beginning of line 2 | |
LCDserial.print("Hot Water "); | |
// temp=Thermistor(analogRead(Therm3)); // read ADC 3 (Tank Outlet) and convert it to Celsius | |
// temp3=temp; // temp3 = Hot Water temperature | |
LCDserial.print("?x10?y2"); // move cursor to beginning of xpos,ypos | |
LCDprintDouble(temp3,2); // display Celsius on the LCD display to 2 dp | |
if (temp3 >= 45) { // Check the hot water temperature | |
LCDserial.print("?x15?y2"); // move cursor to end of line 2 | |
LCDserial.print(" Hot"); // display it | |
} | |
else { | |
LCDserial.print("?x15?y2"); // move cursor to end of line 2 | |
LCDserial.print(" Wait"); // display it | |
} | |
// Print out the roomtemps | |
LCDserial.print("?x00?y3"); // move cursor to beginning of line 3 | |
LCDserial.print("R1 "); | |
LCDserial.print("?x03?y3"); // move cursor to beginning of xpos,ypos | |
LCDprintDouble(temp5,2); // display Celsius on the LCD display to 2 dp | |
LCDserial.print("?x10?y3"); // move cursor to beginning of line 3 | |
LCDserial.print("R2 "); | |
LCDserial.print("?x13?y3"); // move cursor to beginning of xpos,ypos | |
LCDprintDouble(temp1,2); // display Celsius on the LCD display to 2 dp | |
// Print outside temperature | |
// temp=Thermistor(analogRead(Therm0)); // read ADC 0 and convert it to Celsius | |
// Serial.print(" ,"); printDouble(temp,3); // display temperature in Celsius | |
// LCDserial.print("?x03?y1"); // move cursor to beginning of xpos,ypos | |
// LCDprintDouble(temp,2); // display Celsius on the LCD display to 2 dp | |
// temp0 = temp; | |
// temp=Thermistor(analogRead(Therm5)); // read ADC 5 and convert it to Celsius | |
// Serial.print(","); printDouble(temp,3); // display Celsius | |
// temp5 = temp; | |
// temp=Thermistor(analogRead(Therm2)); // read ADC 2 and convert it to Celsius | |
// Serial.print(","); printDouble(temp,3); // display Celsius | |
// temp2 = temp; | |
} | |
//************************************************************************************************* | |
// End of minute_av_temps() | |
//**************************************************************************************************** | |
//******************************************************************************************************************************** | |
// Mode 0 - Display the Start Up Screen | |
//******************************************************************************************************************************** | |
//******************************************************************************************************************************** | |
// Mode 1 - Display the User Friendly Screen | |
//******************************************************************************************************************************** | |
//******************************************************************************************************************************** | |
// Mode 2 - Display the Second User Screen | |
//******************************************************************************************************************************** | |
//******************************************************************************************************************************** | |
// Mode 3 - Display the Diagnostics Screen | |
//******************************************************************************************************************************** | |
//******************************************************************************************************************************** | |
// Mode 4 - Display the Time and Parameter Settings Screen | |
//******************************************************************************************************************************** | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment