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
heating/radiator.c@95:97621bfbedfa, 2020-10-02 (annotated)
- Committer:
- andrewboyson
- Date:
- Fri Oct 02 15:40:53 2020 +0000
- Revision:
- 95:97621bfbedfa
- Parent:
- 76:3ef2a46c8b1e
- Child:
- 96:18a3813bb4b5
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?
User | Revision | Line number | New contents of line |
---|---|---|---|
andrewboyson | 0:3c04f4b47041 | 1 | #include <stdint.h> |
andrewboyson | 0:3c04f4b47041 | 2 | #include <string.h> |
andrewboyson | 0:3c04f4b47041 | 3 | #include <stdbool.h> |
andrewboyson | 0:3c04f4b47041 | 4 | |
andrewboyson | 35:bb8a6d1c034c | 5 | #include "gpio.h" |
andrewboyson | 35:bb8a6d1c034c | 6 | #include "program.h" |
andrewboyson | 35:bb8a6d1c034c | 7 | #include "ds18b20.h" |
andrewboyson | 35:bb8a6d1c034c | 8 | #include "fram.h" |
andrewboyson | 0:3c04f4b47041 | 9 | #include "radiator.h" |
andrewboyson | 95:97621bfbedfa | 10 | #include "clktime.h" |
andrewboyson | 95:97621bfbedfa | 11 | #include "clk.h" |
andrewboyson | 35:bb8a6d1c034c | 12 | #include "led.h" |
andrewboyson | 5:82197a6997fd | 13 | |
andrewboyson | 5:82197a6997fd | 14 | |
andrewboyson | 5:82197a6997fd | 15 | #define RADIATOR_PUMP_DIR FIO2DIR(03) // P2.03 == p23; |
andrewboyson | 5:82197a6997fd | 16 | #define RADIATOR_PUMP_PIN FIO2PIN(03) |
andrewboyson | 5:82197a6997fd | 17 | #define RADIATOR_PUMP_SET FIO2SET(03) |
andrewboyson | 5:82197a6997fd | 18 | #define RADIATOR_PUMP_CLR FIO2CLR(03) |
andrewboyson | 0:3c04f4b47041 | 19 | |
andrewboyson | 95:97621bfbedfa | 20 | static char htgWinter; static int iWinter; |
andrewboyson | 95:97621bfbedfa | 21 | static char htgOverride; static int iOverride; |
andrewboyson | 95:97621bfbedfa | 22 | static char* hallRom; static int iHallRom; |
andrewboyson | 95:97621bfbedfa | 23 | static uint16_t overrideCancelMinute; static int iOverrideCancelMinute; |
andrewboyson | 95:97621bfbedfa | 24 | static int16_t nightTemperature; static int iNightTemperature; |
andrewboyson | 95:97621bfbedfa | 25 | static int16_t frostTemperature; static int iFrostTemperature; |
andrewboyson | 0:3c04f4b47041 | 26 | |
andrewboyson | 95:97621bfbedfa | 27 | bool RadiatorGetWinter () { return (bool)htgWinter; } |
andrewboyson | 95:97621bfbedfa | 28 | bool RadiatorGetOverride () { return (bool)htgOverride; } |
andrewboyson | 95:97621bfbedfa | 29 | uint16_t RadiatorGetHallDS18B20Value () { return DS18B20ValueFromRom(hallRom); } |
andrewboyson | 95:97621bfbedfa | 30 | int RadiatorGetOverrideCancelMinute() { return (int)overrideCancelMinute; } |
andrewboyson | 95:97621bfbedfa | 31 | int RadiatorGetNightTemperature () { return (int)nightTemperature; } |
andrewboyson | 95:97621bfbedfa | 32 | int RadiatorGetFrostTemperature () { return (int)frostTemperature; } |
andrewboyson | 0:3c04f4b47041 | 33 | |
andrewboyson | 95:97621bfbedfa | 34 | static void setWinter ( bool value) { htgWinter = (char)value; FramWrite(iWinter, 1, &htgWinter ); } |
andrewboyson | 95:97621bfbedfa | 35 | static void setOverride ( bool value) { htgOverride = (char)value; FramWrite(iOverride, 1, &htgOverride ); } |
andrewboyson | 95:97621bfbedfa | 36 | static void setHallRom ( char* value) { memcpy(hallRom, value, 8); FramWrite(iHallRom, 8, hallRom ); } |
andrewboyson | 95:97621bfbedfa | 37 | void RadiatorSetOverrideCancelMinute( int value) { overrideCancelMinute = (uint16_t)value, FramWrite(iOverrideCancelMinute, 2, &overrideCancelMinute); } |
andrewboyson | 95:97621bfbedfa | 38 | void RadiatorSetNightTemperature ( int value) { nightTemperature = (int16_t)value; FramWrite(iNightTemperature, 2, &nightTemperature ); } |
andrewboyson | 95:97621bfbedfa | 39 | void RadiatorSetFrostTemperature ( int value) { frostTemperature = (int16_t)value; FramWrite(iFrostTemperature, 2, &frostTemperature ); } |
andrewboyson | 0:3c04f4b47041 | 40 | |
andrewboyson | 0:3c04f4b47041 | 41 | static bool outputBeforeOverride = false; |
andrewboyson | 0:3c04f4b47041 | 42 | static void makeOutputBeforeOverride() |
andrewboyson | 0:3c04f4b47041 | 43 | { |
andrewboyson | 0:3c04f4b47041 | 44 | //See if the temperature is too low |
andrewboyson | 0:3c04f4b47041 | 45 | int hallTemp16ths = DS18B20ValueFromRom(hallRom); |
andrewboyson | 0:3c04f4b47041 | 46 | int nightTemp16ths = nightTemperature << 4; |
andrewboyson | 0:3c04f4b47041 | 47 | int frostTemp16ths = frostTemperature << 4; |
andrewboyson | 0:3c04f4b47041 | 48 | |
andrewboyson | 0:3c04f4b47041 | 49 | static bool tooCold = false; //This is static to ride through invalid temperature reads |
andrewboyson | 0:3c04f4b47041 | 50 | if (DS18B20IsValidValue(hallTemp16ths)) |
andrewboyson | 0:3c04f4b47041 | 51 | { |
andrewboyson | 0:3c04f4b47041 | 52 | tooCold = hallTemp16ths < frostTemp16ths; |
andrewboyson | 57:72c1c1357861 | 53 | if (htgWinter) tooCold |= hallTemp16ths < nightTemp16ths; |
andrewboyson | 0:3c04f4b47041 | 54 | } |
andrewboyson | 0:3c04f4b47041 | 55 | |
andrewboyson | 76:3ef2a46c8b1e | 56 | outputBeforeOverride = (htgWinter && ProgramTimerOutput) || tooCold; |
andrewboyson | 0:3c04f4b47041 | 57 | } |
andrewboyson | 0:3c04f4b47041 | 58 | static void adjustOverride() |
andrewboyson | 0:3c04f4b47041 | 59 | { |
andrewboyson | 95:97621bfbedfa | 60 | |
andrewboyson | 95:97621bfbedfa | 61 | //Remove override at 11pm |
andrewboyson | 95:97621bfbedfa | 62 | if (!ClkTimeIsSet()) |
andrewboyson | 95:97621bfbedfa | 63 | { |
andrewboyson | 95:97621bfbedfa | 64 | struct tm tm; |
andrewboyson | 95:97621bfbedfa | 65 | ClkNowTmLocal(&tm); |
andrewboyson | 95:97621bfbedfa | 66 | static bool timeWasAfter11pm = false; |
andrewboyson | 95:97621bfbedfa | 67 | bool timeIsAfter11pm = tm.tm_hour >= 23; |
andrewboyson | 95:97621bfbedfa | 68 | if (timeIsAfter11pm && !timeWasAfter11pm && htgOverride) setOverride(false); |
andrewboyson | 95:97621bfbedfa | 69 | timeWasAfter11pm = timeIsAfter11pm; |
andrewboyson | 95:97621bfbedfa | 70 | } |
andrewboyson | 95:97621bfbedfa | 71 | |
andrewboyson | 95:97621bfbedfa | 72 | //Remove override if no longer required |
andrewboyson | 0:3c04f4b47041 | 73 | static bool previousOutput = false; |
andrewboyson | 0:3c04f4b47041 | 74 | if (previousOutput != outputBeforeOverride) setOverride(false); |
andrewboyson | 0:3c04f4b47041 | 75 | previousOutput = outputBeforeOverride; |
andrewboyson | 0:3c04f4b47041 | 76 | } |
andrewboyson | 0:3c04f4b47041 | 77 | bool RadiatorPump = false; |
andrewboyson | 0:3c04f4b47041 | 78 | static void makeOutputWithOverride() |
andrewboyson | 0:3c04f4b47041 | 79 | { |
andrewboyson | 0:3c04f4b47041 | 80 | RadiatorPump = htgOverride ? !outputBeforeOverride : outputBeforeOverride ; |
andrewboyson | 0:3c04f4b47041 | 81 | } |
andrewboyson | 0:3c04f4b47041 | 82 | |
andrewboyson | 57:72c1c1357861 | 83 | void RadiatorSetWinter(bool value) //Summer is false, Winter is true |
andrewboyson | 0:3c04f4b47041 | 84 | { |
andrewboyson | 57:72c1c1357861 | 85 | if (htgWinter == (char)value) return; //Ignore no change |
andrewboyson | 57:72c1c1357861 | 86 | setWinter(value); //Change to the new value |
andrewboyson | 0:3c04f4b47041 | 87 | |
andrewboyson | 0:3c04f4b47041 | 88 | bool prevOutputBeforeOverride = outputBeforeOverride; |
andrewboyson | 0:3c04f4b47041 | 89 | makeOutputBeforeOverride(); |
andrewboyson | 0:3c04f4b47041 | 90 | |
andrewboyson | 0:3c04f4b47041 | 91 | if (htgOverride) //Only deal with an override that is already set; if it wasn't set don't change it |
andrewboyson | 0:3c04f4b47041 | 92 | { |
andrewboyson | 57:72c1c1357861 | 93 | if (htgWinter) //Summer -> Winter |
andrewboyson | 0:3c04f4b47041 | 94 | { |
andrewboyson | 0:3c04f4b47041 | 95 | if (outputBeforeOverride != prevOutputBeforeOverride) setOverride(0); //Adjust the override to leave the heat as it was - off or on. |
andrewboyson | 0:3c04f4b47041 | 96 | } |
andrewboyson | 0:3c04f4b47041 | 97 | else //Winter -> Summer |
andrewboyson | 0:3c04f4b47041 | 98 | { |
andrewboyson | 0:3c04f4b47041 | 99 | setOverride(0); //turn off the heat. |
andrewboyson | 0:3c04f4b47041 | 100 | } |
andrewboyson | 0:3c04f4b47041 | 101 | } |
andrewboyson | 0:3c04f4b47041 | 102 | |
andrewboyson | 0:3c04f4b47041 | 103 | makeOutputWithOverride(); |
andrewboyson | 0:3c04f4b47041 | 104 | } |
andrewboyson | 0:3c04f4b47041 | 105 | void RadiatorSetOverride(bool value) |
andrewboyson | 0:3c04f4b47041 | 106 | { |
andrewboyson | 0:3c04f4b47041 | 107 | setOverride(value); |
andrewboyson | 0:3c04f4b47041 | 108 | makeOutputBeforeOverride(); |
andrewboyson | 0:3c04f4b47041 | 109 | makeOutputWithOverride(); } |
andrewboyson | 0:3c04f4b47041 | 110 | |
andrewboyson | 57:72c1c1357861 | 111 | void RadiatorChgWinter (){ RadiatorSetWinter (!RadiatorGetWinter ()); } |
andrewboyson | 0:3c04f4b47041 | 112 | void RadiatorChgOverride(){ RadiatorSetOverride(!RadiatorGetOverride()); } |
andrewboyson | 0:3c04f4b47041 | 113 | |
andrewboyson | 0:3c04f4b47041 | 114 | int RadiatorInit() |
andrewboyson | 0:3c04f4b47041 | 115 | { |
andrewboyson | 48:6eac12df3ad5 | 116 | hallRom = DS18B20Roms + 8 * DS18B20RomCount; |
andrewboyson | 48:6eac12df3ad5 | 117 | DS18B20RomSetters[DS18B20RomCount] = setHallRom; |
andrewboyson | 48:6eac12df3ad5 | 118 | DS18B20RomNames[DS18B20RomCount] = "Hall"; |
andrewboyson | 48:6eac12df3ad5 | 119 | DS18B20RomCount++; |
andrewboyson | 48:6eac12df3ad5 | 120 | |
andrewboyson | 0:3c04f4b47041 | 121 | int address; |
andrewboyson | 0:3c04f4b47041 | 122 | char def1; |
andrewboyson | 95:97621bfbedfa | 123 | int16_t def2; |
andrewboyson | 95:97621bfbedfa | 124 | def1 = 0; address = FramLoad( 1, &htgWinter, &def1); if (address < 0) return -1; iWinter = address; |
andrewboyson | 95:97621bfbedfa | 125 | def1 = 0; address = FramLoad( 1, &htgOverride, &def1); if (address < 0) return -1; iOverride = address; |
andrewboyson | 95:97621bfbedfa | 126 | address = FramLoad( 8, hallRom, 0); if (address < 0) return -1; iHallRom = address; |
andrewboyson | 95:97621bfbedfa | 127 | def2 = 23*60; address = FramLoad( 2, &overrideCancelMinute, &def2); if (address < 0) return -1; iOverrideCancelMinute = address; |
andrewboyson | 95:97621bfbedfa | 128 | FramAllocate(2); //Spare two bytes |
andrewboyson | 95:97621bfbedfa | 129 | def2 = 15; address = FramLoad( 2, &nightTemperature, &def2); if (address < 0) return -1; iNightTemperature = address; |
andrewboyson | 95:97621bfbedfa | 130 | def2 = 8; address = FramLoad( 2, &frostTemperature, &def2); if (address < 0) return -1; iFrostTemperature = address; |
andrewboyson | 0:3c04f4b47041 | 131 | |
andrewboyson | 5:82197a6997fd | 132 | RADIATOR_PUMP_DIR = 1; //Set the direction to 1 == output |
andrewboyson | 0:3c04f4b47041 | 133 | |
andrewboyson | 0:3c04f4b47041 | 134 | return 0; |
andrewboyson | 0:3c04f4b47041 | 135 | } |
andrewboyson | 0:3c04f4b47041 | 136 | void RadiatorMain() |
andrewboyson | 0:3c04f4b47041 | 137 | { |
andrewboyson | 0:3c04f4b47041 | 138 | //Make the radiator output |
andrewboyson | 0:3c04f4b47041 | 139 | makeOutputBeforeOverride(); |
andrewboyson | 0:3c04f4b47041 | 140 | adjustOverride(); |
andrewboyson | 0:3c04f4b47041 | 141 | makeOutputWithOverride(); |
andrewboyson | 0:3c04f4b47041 | 142 | |
andrewboyson | 0:3c04f4b47041 | 143 | //Pump output |
andrewboyson | 5:82197a6997fd | 144 | if (RadiatorPump) RADIATOR_PUMP_SET; |
andrewboyson | 5:82197a6997fd | 145 | else RADIATOR_PUMP_CLR; |
andrewboyson | 0:3c04f4b47041 | 146 | |
andrewboyson | 0:3c04f4b47041 | 147 | } |