Central Heating controller using the real time clock, PHY module for internet, 1-wire interface for temperature sensors, a system log and a configuration file

Dependencies:   net 1-wire lpc1768 crypto clock web fram log

/media/uploads/andrewboyson/heating.sch

/media/uploads/andrewboyson/heating.brd

/media/uploads/andrewboyson/eagle.epf

Committer:
andrewboyson
Date:
Fri Oct 02 15:40:53 2020 +0000
Revision:
95:97621bfbedfa
Parent:
48:6eac12df3ad5
Added 11pm override cancel for the radiators as we kept forgetting to remove the override if used in the summer. Space in the Fram memory for the minute in the day to cancel was found. Still to do the web UI.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 0:3c04f4b47041 1 #include <stdint.h>
andrewboyson 0:3c04f4b47041 2 #include <stdlib.h>
andrewboyson 0:3c04f4b47041 3 #include <stdbool.h>
andrewboyson 0:3c04f4b47041 4
andrewboyson 95:97621bfbedfa 5 #include "rtc.h"
andrewboyson 20:904a4f043f2c 6 #include "clktime.h"
andrewboyson 95:97621bfbedfa 7 #include "clk.h"
andrewboyson 95:97621bfbedfa 8 #include "log.h"
andrewboyson 20:904a4f043f2c 9 #include "fram.h"
andrewboyson 48:6eac12df3ad5 10 #include "http.h"
andrewboyson 0:3c04f4b47041 11
andrewboyson 48:6eac12df3ad5 12 #define PROGRAMS_COUNT 3
andrewboyson 47:229338b3adcb 13 #define TRANSITIONS_COUNT 4
andrewboyson 47:229338b3adcb 14 static int16_t programs[PROGRAMS_COUNT][TRANSITIONS_COUNT]; static int iPrograms;
andrewboyson 47:229338b3adcb 15 static char programDay[7]; static int iDay;
andrewboyson 47:229338b3adcb 16 static char programNewDayHour; static int iNewDayHour;
andrewboyson 0:3c04f4b47041 17
andrewboyson 0:3c04f4b47041 18 int ProgramGetDay (int i) { return (int) programDay[i]; }
andrewboyson 0:3c04f4b47041 19 int ProgramGetNewDayHour() { return (int) programNewDayHour;}
andrewboyson 0:3c04f4b47041 20
andrewboyson 0:3c04f4b47041 21 void ProgramSetDay (int i, int value) { programDay [i] = (char)value; FramWrite(iDay + i, 1, &programDay [i]); }
andrewboyson 0:3c04f4b47041 22 void ProgramSetNewDayHour( int value) { programNewDayHour = (char)value; FramWrite(iNewDayHour, 1, &programNewDayHour ); }
andrewboyson 0:3c04f4b47041 23
andrewboyson 0:3c04f4b47041 24 int ProgramInit()
andrewboyson 0:3c04f4b47041 25 {
andrewboyson 0:3c04f4b47041 26 char def1;
andrewboyson 0:3c04f4b47041 27 int address;
andrewboyson 47:229338b3adcb 28 int programSize = PROGRAMS_COUNT * TRANSITIONS_COUNT * sizeof(int16_t);
andrewboyson 0:3c04f4b47041 29 address = FramLoad(7, programDay, NULL); if (address < 0) return -1; iDay = address;
andrewboyson 0:3c04f4b47041 30 address = FramLoad(programSize, programs, NULL); if (address < 0) return -1; iPrograms = address; //3 x 4 x 2
andrewboyson 0:3c04f4b47041 31 def1 = 2; address = FramLoad(1, &programNewDayHour, &def1); if (address < 0) return -1; iNewDayHour = address;
andrewboyson 0:3c04f4b47041 32 return 0;
andrewboyson 0:3c04f4b47041 33 }
andrewboyson 0:3c04f4b47041 34
andrewboyson 0:3c04f4b47041 35 /*
andrewboyson 0:3c04f4b47041 36 There are three programs available [0|1|2]; any of which can be allocated to a given day [0-6].
andrewboyson 0:3c04f4b47041 37 Each program contains four transitions with an index [0|1|2|3].
andrewboyson 0:3c04f4b47041 38 A transition is defined to be a short (16 bit) and consists of:
andrewboyson 0:3c04f4b47041 39 +---------+--------+--------+---------+
andrewboyson 0:3c04f4b47041 40 | 15 - 13 | 12 | 11 | 10 - 00 |
andrewboyson 0:3c04f4b47041 41 +---------+--------+--------+---------+
andrewboyson 0:3c04f4b47041 42 | | in use | switch | minute |
andrewboyson 0:3c04f4b47041 43 | | yes/no | on/off | in day |
andrewboyson 0:3c04f4b47041 44 | | 1/0 | 1/0 | 0-1439 |
andrewboyson 0:3c04f4b47041 45 +---------+--------+--------+---------+
andrewboyson 0:3c04f4b47041 46 */
andrewboyson 0:3c04f4b47041 47 static int16_t encodeTransition(bool inuse, bool onoff, int minutes)
andrewboyson 0:3c04f4b47041 48 {
andrewboyson 0:3c04f4b47041 49 int16_t transition = minutes;
andrewboyson 0:3c04f4b47041 50 transition &= 0x07FF;
andrewboyson 0:3c04f4b47041 51 if (onoff) transition |= 0x0800;
andrewboyson 0:3c04f4b47041 52 if (inuse) transition |= 0x1000;
andrewboyson 0:3c04f4b47041 53 return transition;
andrewboyson 0:3c04f4b47041 54 }
andrewboyson 0:3c04f4b47041 55 static void decodeTransition(int16_t transition, bool* pinuse, bool* ponoff, int* pminutes)
andrewboyson 0:3c04f4b47041 56 {
andrewboyson 0:3c04f4b47041 57 *pinuse = transition & 0x1000;
andrewboyson 0:3c04f4b47041 58 *ponoff = transition & 0x0800;
andrewboyson 0:3c04f4b47041 59 *pminutes = transition & 0x07FF;
andrewboyson 0:3c04f4b47041 60 }
andrewboyson 0:3c04f4b47041 61
andrewboyson 0:3c04f4b47041 62 static int compareTransition (const void * a, const void * b) //-ve a goes before b; 0 same; +ve a goes after b
andrewboyson 0:3c04f4b47041 63 {
andrewboyson 0:3c04f4b47041 64 bool inUseA, inUseB;
andrewboyson 0:3c04f4b47041 65 bool onA, onB;
andrewboyson 0:3c04f4b47041 66 int minutesA, minutesB;
andrewboyson 0:3c04f4b47041 67 decodeTransition(*(int16_t*)a, &inUseA, &onA, &minutesA);
andrewboyson 0:3c04f4b47041 68 decodeTransition(*(int16_t*)b, &inUseB, &onB, &minutesB);
andrewboyson 0:3c04f4b47041 69
andrewboyson 0:3c04f4b47041 70 if (!inUseA && !inUseB) return 0;
andrewboyson 0:3c04f4b47041 71 if (!inUseA) return +1;
andrewboyson 0:3c04f4b47041 72 if (!inUseB) return -1;
andrewboyson 0:3c04f4b47041 73
andrewboyson 0:3c04f4b47041 74 if (minutesA < programNewDayHour * 60) minutesA += 1440;
andrewboyson 0:3c04f4b47041 75 if (minutesB < programNewDayHour * 60) minutesB += 1440;
andrewboyson 0:3c04f4b47041 76
andrewboyson 0:3c04f4b47041 77 if (minutesA < minutesB) return -1;
andrewboyson 0:3c04f4b47041 78 if (minutesA > minutesB) return +1;
andrewboyson 0:3c04f4b47041 79 return 0;
andrewboyson 0:3c04f4b47041 80 }
andrewboyson 0:3c04f4b47041 81 static void sort(int16_t* pProgram)
andrewboyson 0:3c04f4b47041 82 {
andrewboyson 0:3c04f4b47041 83 qsort (pProgram, 4, sizeof(int16_t), compareTransition);
andrewboyson 0:3c04f4b47041 84 }
andrewboyson 0:3c04f4b47041 85
andrewboyson 0:3c04f4b47041 86 //[+|-][00-23][00-59];
andrewboyson 0:3c04f4b47041 87 void ProgramToString(int program, int buflen, char* buffer)
andrewboyson 0:3c04f4b47041 88 {
andrewboyson 0:3c04f4b47041 89 if (buflen < 25) return;
andrewboyson 0:3c04f4b47041 90 char* p = buffer;
andrewboyson 47:229338b3adcb 91 for (int i = 0; i < TRANSITIONS_COUNT; i++)
andrewboyson 0:3c04f4b47041 92 {
andrewboyson 0:3c04f4b47041 93 int16_t transition = programs[program][i];
andrewboyson 0:3c04f4b47041 94 bool inuse;
andrewboyson 0:3c04f4b47041 95 bool on;
andrewboyson 0:3c04f4b47041 96 int minuteUnits;
andrewboyson 0:3c04f4b47041 97 decodeTransition(transition, &inuse, &on, &minuteUnits);
andrewboyson 0:3c04f4b47041 98 if (!inuse) continue;
andrewboyson 0:3c04f4b47041 99
andrewboyson 0:3c04f4b47041 100 int minuteTens = minuteUnits / 10; minuteUnits %= 10;
andrewboyson 0:3c04f4b47041 101 int hourUnits = minuteTens / 6; minuteTens %= 6;
andrewboyson 0:3c04f4b47041 102 int hourTens = hourUnits / 10; hourUnits %= 10;
andrewboyson 0:3c04f4b47041 103
andrewboyson 0:3c04f4b47041 104 if (p > buffer) *p++ = ' ';
andrewboyson 0:3c04f4b47041 105 *p++ = on ? '+' : '-';
andrewboyson 0:3c04f4b47041 106 *p++ = hourTens + '0';
andrewboyson 0:3c04f4b47041 107 *p++ = hourUnits + '0';
andrewboyson 0:3c04f4b47041 108 *p++ = minuteTens + '0';
andrewboyson 0:3c04f4b47041 109 *p++ = minuteUnits + '0';
andrewboyson 0:3c04f4b47041 110 }
andrewboyson 0:3c04f4b47041 111 *p = 0;
andrewboyson 0:3c04f4b47041 112 }
andrewboyson 48:6eac12df3ad5 113 void ProgramSendAjax()
andrewboyson 48:6eac12df3ad5 114 {
andrewboyson 48:6eac12df3ad5 115 for (int program = 0; program < PROGRAMS_COUNT; program++)
andrewboyson 48:6eac12df3ad5 116 {
andrewboyson 48:6eac12df3ad5 117 for (int transition = 0; transition < TRANSITIONS_COUNT; transition++)
andrewboyson 48:6eac12df3ad5 118 {
andrewboyson 48:6eac12df3ad5 119 bool inuse;
andrewboyson 48:6eac12df3ad5 120 bool on;
andrewboyson 48:6eac12df3ad5 121 int minuteUnits;
andrewboyson 48:6eac12df3ad5 122 decodeTransition(programs[program][transition], &inuse, &on, &minuteUnits);
andrewboyson 48:6eac12df3ad5 123 if (!inuse) continue;
andrewboyson 48:6eac12df3ad5 124
andrewboyson 48:6eac12df3ad5 125 int minuteTens = minuteUnits / 10; minuteUnits %= 10;
andrewboyson 48:6eac12df3ad5 126 int hourUnits = minuteTens / 6; minuteTens %= 6;
andrewboyson 48:6eac12df3ad5 127 int hourTens = hourUnits / 10; hourUnits %= 10;
andrewboyson 48:6eac12df3ad5 128
andrewboyson 48:6eac12df3ad5 129 if (transition) HttpAddChar(' ');
andrewboyson 48:6eac12df3ad5 130 HttpAddChar(on ? '+' : '-');
andrewboyson 48:6eac12df3ad5 131 HttpAddChar(hourTens + '0');
andrewboyson 48:6eac12df3ad5 132 HttpAddChar(hourUnits + '0');
andrewboyson 48:6eac12df3ad5 133 HttpAddChar(minuteTens + '0');
andrewboyson 48:6eac12df3ad5 134 HttpAddChar(minuteUnits + '0');
andrewboyson 48:6eac12df3ad5 135 }
andrewboyson 48:6eac12df3ad5 136 HttpAddChar('\n');
andrewboyson 48:6eac12df3ad5 137 }
andrewboyson 48:6eac12df3ad5 138 }
andrewboyson 0:3c04f4b47041 139 static void handleParseDelim(int program, int* pIndex, bool* pInUse, bool* pOn, int* pHourTens, int* pHourUnits, int* pMinuteTens, int* pMinuteUnits)
andrewboyson 0:3c04f4b47041 140 {
andrewboyson 0:3c04f4b47041 141 int hour = *pHourTens * 10 + *pHourUnits;
andrewboyson 0:3c04f4b47041 142 if (hour < 0) *pInUse = false;
andrewboyson 0:3c04f4b47041 143 if (hour > 23) *pInUse = false;
andrewboyson 0:3c04f4b47041 144
andrewboyson 0:3c04f4b47041 145 int minute = *pMinuteTens * 10 + *pMinuteUnits;
andrewboyson 0:3c04f4b47041 146 if (minute < 0) *pInUse = false;
andrewboyson 0:3c04f4b47041 147 if (minute > 59) *pInUse = false;
andrewboyson 0:3c04f4b47041 148
andrewboyson 0:3c04f4b47041 149 int minutes = hour * 60 + minute;
andrewboyson 0:3c04f4b47041 150
andrewboyson 0:3c04f4b47041 151 int16_t transition = encodeTransition(*pInUse, *pOn, minutes);
andrewboyson 0:3c04f4b47041 152 programs[program][*pIndex] = transition;
andrewboyson 0:3c04f4b47041 153
andrewboyson 0:3c04f4b47041 154 *pIndex += 1;
andrewboyson 0:3c04f4b47041 155 *pInUse = 0;
andrewboyson 0:3c04f4b47041 156 *pOn = 0;
andrewboyson 0:3c04f4b47041 157 *pHourTens = 0;
andrewboyson 0:3c04f4b47041 158 *pHourUnits = 0;
andrewboyson 0:3c04f4b47041 159 *pMinuteTens = 0;
andrewboyson 0:3c04f4b47041 160 *pMinuteUnits = 0;
andrewboyson 0:3c04f4b47041 161
andrewboyson 0:3c04f4b47041 162 }
andrewboyson 0:3c04f4b47041 163 void ProgramParse(int program, char* p)
andrewboyson 0:3c04f4b47041 164 {
andrewboyson 0:3c04f4b47041 165 int i = 0;
andrewboyson 0:3c04f4b47041 166 bool inUse = 0; bool on = 0;
andrewboyson 0:3c04f4b47041 167 int hourUnits = 0; int hourTens = 0;
andrewboyson 0:3c04f4b47041 168 int minuteUnits = 0; int minuteTens = 0;
andrewboyson 47:229338b3adcb 169 while (*p && i < TRANSITIONS_COUNT)
andrewboyson 0:3c04f4b47041 170 {
andrewboyson 0:3c04f4b47041 171 if (*p == '+') { on = true ; }
andrewboyson 0:3c04f4b47041 172 else if (*p == '-') { on = false; }
andrewboyson 0:3c04f4b47041 173 else if (*p >= '0' && *p <= '9') { inUse = true; hourTens = hourUnits; hourUnits = minuteTens; minuteTens = minuteUnits; minuteUnits = *p - '0'; }
andrewboyson 0:3c04f4b47041 174 else if (*p == ' ') { handleParseDelim(program, &i, &inUse, &on, &hourTens, &hourUnits, &minuteTens, &minuteUnits); }
andrewboyson 0:3c04f4b47041 175 p++;
andrewboyson 0:3c04f4b47041 176 }
andrewboyson 47:229338b3adcb 177 while (i < TRANSITIONS_COUNT) handleParseDelim(program, &i, &inUse, &on, &hourTens, &hourUnits, &minuteTens, &minuteUnits);
andrewboyson 0:3c04f4b47041 178 sort(&programs[program][0]);
andrewboyson 0:3c04f4b47041 179 FramWrite(iPrograms + program * 8, 8, &programs[program]);
andrewboyson 0:3c04f4b47041 180 }
andrewboyson 0:3c04f4b47041 181
andrewboyson 0:3c04f4b47041 182 static bool readProgramTimerOutput()
andrewboyson 0:3c04f4b47041 183 {
andrewboyson 0:3c04f4b47041 184
andrewboyson 20:904a4f043f2c 185 if (!ClkTimeIsSet()) return 0;
andrewboyson 0:3c04f4b47041 186
andrewboyson 0:3c04f4b47041 187 struct tm tm;
andrewboyson 20:904a4f043f2c 188 ClkNowTmLocal(&tm);
andrewboyson 0:3c04f4b47041 189
andrewboyson 0:3c04f4b47041 190 int dayOfWeek = tm.tm_wday;
andrewboyson 0:3c04f4b47041 191 int minutesNow = tm.tm_hour * 60 + tm.tm_min;
andrewboyson 0:3c04f4b47041 192 if (tm.tm_hour < programNewDayHour) //Before 2am should be matched against yesterday's program.
andrewboyson 0:3c04f4b47041 193 {
andrewboyson 0:3c04f4b47041 194 dayOfWeek--;
andrewboyson 0:3c04f4b47041 195 if (dayOfWeek < 0) dayOfWeek = 6;
andrewboyson 0:3c04f4b47041 196 }
andrewboyson 0:3c04f4b47041 197
andrewboyson 0:3c04f4b47041 198 int program = programDay[dayOfWeek];
andrewboyson 0:3c04f4b47041 199
andrewboyson 0:3c04f4b47041 200 bool calling = 0;
andrewboyson 47:229338b3adcb 201 for (int i = 0; i < TRANSITIONS_COUNT; i++)
andrewboyson 0:3c04f4b47041 202 {
andrewboyson 0:3c04f4b47041 203 int16_t transition = programs[program][i];
andrewboyson 0:3c04f4b47041 204 bool inuse;
andrewboyson 0:3c04f4b47041 205 bool on;
andrewboyson 0:3c04f4b47041 206 int minutes;
andrewboyson 0:3c04f4b47041 207 decodeTransition(transition, &inuse, &on, &minutes);
andrewboyson 0:3c04f4b47041 208 if (!inuse) continue;
andrewboyson 0:3c04f4b47041 209 if (minutes <= minutesNow) calling = on;
andrewboyson 0:3c04f4b47041 210 }
andrewboyson 0:3c04f4b47041 211
andrewboyson 0:3c04f4b47041 212 return calling;
andrewboyson 0:3c04f4b47041 213 }
andrewboyson 0:3c04f4b47041 214
andrewboyson 0:3c04f4b47041 215 bool ProgramTimerOutput;
andrewboyson 0:3c04f4b47041 216
andrewboyson 0:3c04f4b47041 217 int ProgramMain()
andrewboyson 0:3c04f4b47041 218 {
andrewboyson 0:3c04f4b47041 219 ProgramTimerOutput = readProgramTimerOutput();
andrewboyson 0:3c04f4b47041 220 return 0;
andrewboyson 0:3c04f4b47041 221 }