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@106:41ed3ea0bbba, 2021-04-23 (annotated)
- Committer:
- andrewboyson
- Date:
- Fri Apr 23 08:36:42 2021 +0000
- Revision:
- 106:41ed3ea0bbba
- Parent:
- 102:d7bc31f0ac6e
Not working, crashes.
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 | 98:c75c959bcde3 | 20 | static bool htgOverride = false; |
andrewboyson | 95:97621bfbedfa | 21 | static char htgWinter; static int iWinter; |
andrewboyson | 95:97621bfbedfa | 22 | static char* hallRom; static int iHallRom; |
andrewboyson | 99:84c3273dc77f | 23 | static uint8_t overrideCancelHour; static int iOverrideCancelHour; |
andrewboyson | 99:84c3273dc77f | 24 | static uint8_t overrideCancelMinute; static int iOverrideCancelMinute; |
andrewboyson | 95:97621bfbedfa | 25 | static int16_t nightTemperature; static int iNightTemperature; |
andrewboyson | 95:97621bfbedfa | 26 | static int16_t frostTemperature; static int iFrostTemperature; |
andrewboyson | 0:3c04f4b47041 | 27 | |
andrewboyson | 95:97621bfbedfa | 28 | bool RadiatorGetWinter () { return (bool)htgWinter; } |
andrewboyson | 98:c75c959bcde3 | 29 | bool RadiatorGetOverride () { return htgOverride; } |
andrewboyson | 95:97621bfbedfa | 30 | uint16_t RadiatorGetHallDS18B20Value () { return DS18B20ValueFromRom(hallRom); } |
andrewboyson | 96:18a3813bb4b5 | 31 | int RadiatorGetOverrideCancelHour () { return (int)overrideCancelHour; } |
andrewboyson | 96:18a3813bb4b5 | 32 | int RadiatorGetOverrideCancelMinute() { return (int)overrideCancelMinute; } |
andrewboyson | 95:97621bfbedfa | 33 | int RadiatorGetNightTemperature () { return (int)nightTemperature; } |
andrewboyson | 95:97621bfbedfa | 34 | int RadiatorGetFrostTemperature () { return (int)frostTemperature; } |
andrewboyson | 0:3c04f4b47041 | 35 | |
andrewboyson | 97:84d58bf7a835 | 36 | static void setWinter ( bool v) { htgWinter = (char)v; FramWrite(iWinter, 1, &htgWinter ); } |
andrewboyson | 97:84d58bf7a835 | 37 | static void setHallRom ( char* v) { memcpy(hallRom, v, 8); FramWrite(iHallRom, 8, hallRom ); } |
andrewboyson | 97:84d58bf7a835 | 38 | void RadiatorSetOverrideCancelHour ( int v) { if (v > 23 || v < 0) v = 0; overrideCancelHour = (uint8_t)v, FramWrite(iOverrideCancelHour, 1, &overrideCancelHour ); } |
andrewboyson | 97:84d58bf7a835 | 39 | void RadiatorSetOverrideCancelMinute( int v) { if (v > 59 || v < 0) v = 0; overrideCancelMinute = (uint8_t)v, FramWrite(iOverrideCancelMinute, 1, &overrideCancelMinute); } |
andrewboyson | 97:84d58bf7a835 | 40 | void RadiatorSetNightTemperature ( int v) { if (v > 99 || v < 0) v = 0; nightTemperature = (int16_t)v; FramWrite(iNightTemperature, 2, &nightTemperature ); } |
andrewboyson | 97:84d58bf7a835 | 41 | void RadiatorSetFrostTemperature ( int v) { if (v > 99 || v < 0) v = 0; frostTemperature = (int16_t)v; FramWrite(iFrostTemperature, 2, &frostTemperature ); } |
andrewboyson | 0:3c04f4b47041 | 42 | |
andrewboyson | 0:3c04f4b47041 | 43 | static bool outputBeforeOverride = false; |
andrewboyson | 0:3c04f4b47041 | 44 | static void makeOutputBeforeOverride() |
andrewboyson | 0:3c04f4b47041 | 45 | { |
andrewboyson | 0:3c04f4b47041 | 46 | //See if the temperature is too low |
andrewboyson | 0:3c04f4b47041 | 47 | int hallTemp16ths = DS18B20ValueFromRom(hallRom); |
andrewboyson | 0:3c04f4b47041 | 48 | int nightTemp16ths = nightTemperature << 4; |
andrewboyson | 0:3c04f4b47041 | 49 | int frostTemp16ths = frostTemperature << 4; |
andrewboyson | 0:3c04f4b47041 | 50 | |
andrewboyson | 0:3c04f4b47041 | 51 | static bool tooCold = false; //This is static to ride through invalid temperature reads |
andrewboyson | 102:d7bc31f0ac6e | 52 | |
andrewboyson | 102:d7bc31f0ac6e | 53 | static bool nightTooCold = false; |
andrewboyson | 102:d7bc31f0ac6e | 54 | static bool frostTooCold = false; |
andrewboyson | 102:d7bc31f0ac6e | 55 | |
andrewboyson | 0:3c04f4b47041 | 56 | if (DS18B20IsValidValue(hallTemp16ths)) |
andrewboyson | 0:3c04f4b47041 | 57 | { |
andrewboyson | 102:d7bc31f0ac6e | 58 | if (hallTemp16ths < frostTemp16ths) frostTooCold = true; |
andrewboyson | 102:d7bc31f0ac6e | 59 | if (hallTemp16ths > frostTemp16ths) frostTooCold = false; |
andrewboyson | 102:d7bc31f0ac6e | 60 | if (hallTemp16ths < nightTemp16ths) nightTooCold = true; //Set at 289 (18.06) rather than 288 (18.00) |
andrewboyson | 102:d7bc31f0ac6e | 61 | if (hallTemp16ths > nightTemp16ths) nightTooCold = false;//Reset at 287 (17.94). This prevent it following the flashing. |
andrewboyson | 0:3c04f4b47041 | 62 | } |
andrewboyson | 0:3c04f4b47041 | 63 | |
andrewboyson | 102:d7bc31f0ac6e | 64 | outputBeforeOverride = (htgWinter && ProgramTimerOutput) || (htgWinter && nightTooCold) || frostTooCold; |
andrewboyson | 0:3c04f4b47041 | 65 | } |
andrewboyson | 96:18a3813bb4b5 | 66 | static void autoCancelOverride() |
andrewboyson | 0:3c04f4b47041 | 67 | { |
andrewboyson | 95:97621bfbedfa | 68 | |
andrewboyson | 95:97621bfbedfa | 69 | //Remove override at 11pm |
andrewboyson | 96:18a3813bb4b5 | 70 | if (ClkTimeIsSet()) |
andrewboyson | 95:97621bfbedfa | 71 | { |
andrewboyson | 95:97621bfbedfa | 72 | struct tm tm; |
andrewboyson | 95:97621bfbedfa | 73 | ClkNowTmLocal(&tm); |
andrewboyson | 96:18a3813bb4b5 | 74 | static bool cancelWasDue = false; |
andrewboyson | 96:18a3813bb4b5 | 75 | bool cancelIsDue = tm.tm_hour == overrideCancelHour && tm.tm_min == overrideCancelMinute; |
andrewboyson | 98:c75c959bcde3 | 76 | if (cancelIsDue && !cancelWasDue && htgOverride) htgOverride = false; |
andrewboyson | 96:18a3813bb4b5 | 77 | cancelWasDue = cancelIsDue; |
andrewboyson | 95:97621bfbedfa | 78 | } |
andrewboyson | 95:97621bfbedfa | 79 | |
andrewboyson | 95:97621bfbedfa | 80 | //Remove override if no longer required |
andrewboyson | 0:3c04f4b47041 | 81 | static bool previousOutput = false; |
andrewboyson | 98:c75c959bcde3 | 82 | if (previousOutput != outputBeforeOverride && htgOverride) htgOverride = false; |
andrewboyson | 0:3c04f4b47041 | 83 | previousOutput = outputBeforeOverride; |
andrewboyson | 0:3c04f4b47041 | 84 | } |
andrewboyson | 0:3c04f4b47041 | 85 | bool RadiatorPump = false; |
andrewboyson | 0:3c04f4b47041 | 86 | static void makeOutputWithOverride() |
andrewboyson | 0:3c04f4b47041 | 87 | { |
andrewboyson | 0:3c04f4b47041 | 88 | RadiatorPump = htgOverride ? !outputBeforeOverride : outputBeforeOverride ; |
andrewboyson | 0:3c04f4b47041 | 89 | } |
andrewboyson | 0:3c04f4b47041 | 90 | |
andrewboyson | 57:72c1c1357861 | 91 | void RadiatorSetWinter(bool value) //Summer is false, Winter is true |
andrewboyson | 0:3c04f4b47041 | 92 | { |
andrewboyson | 57:72c1c1357861 | 93 | if (htgWinter == (char)value) return; //Ignore no change |
andrewboyson | 57:72c1c1357861 | 94 | setWinter(value); //Change to the new value |
andrewboyson | 0:3c04f4b47041 | 95 | |
andrewboyson | 0:3c04f4b47041 | 96 | bool prevOutputBeforeOverride = outputBeforeOverride; |
andrewboyson | 0:3c04f4b47041 | 97 | makeOutputBeforeOverride(); |
andrewboyson | 0:3c04f4b47041 | 98 | |
andrewboyson | 0:3c04f4b47041 | 99 | if (htgOverride) //Only deal with an override that is already set; if it wasn't set don't change it |
andrewboyson | 0:3c04f4b47041 | 100 | { |
andrewboyson | 57:72c1c1357861 | 101 | if (htgWinter) //Summer -> Winter |
andrewboyson | 0:3c04f4b47041 | 102 | { |
andrewboyson | 98:c75c959bcde3 | 103 | if (outputBeforeOverride != prevOutputBeforeOverride) htgOverride = false; //Adjust the override to leave the heat as it was - off or on. |
andrewboyson | 0:3c04f4b47041 | 104 | } |
andrewboyson | 0:3c04f4b47041 | 105 | else //Winter -> Summer |
andrewboyson | 0:3c04f4b47041 | 106 | { |
andrewboyson | 98:c75c959bcde3 | 107 | htgOverride = false; //turn off the heat. |
andrewboyson | 0:3c04f4b47041 | 108 | } |
andrewboyson | 0:3c04f4b47041 | 109 | } |
andrewboyson | 0:3c04f4b47041 | 110 | |
andrewboyson | 0:3c04f4b47041 | 111 | makeOutputWithOverride(); |
andrewboyson | 0:3c04f4b47041 | 112 | } |
andrewboyson | 0:3c04f4b47041 | 113 | void RadiatorSetOverride(bool value) |
andrewboyson | 0:3c04f4b47041 | 114 | { |
andrewboyson | 98:c75c959bcde3 | 115 | htgOverride = value; |
andrewboyson | 0:3c04f4b47041 | 116 | makeOutputBeforeOverride(); |
andrewboyson | 0:3c04f4b47041 | 117 | makeOutputWithOverride(); } |
andrewboyson | 0:3c04f4b47041 | 118 | |
andrewboyson | 57:72c1c1357861 | 119 | void RadiatorChgWinter (){ RadiatorSetWinter (!RadiatorGetWinter ()); } |
andrewboyson | 0:3c04f4b47041 | 120 | void RadiatorChgOverride(){ RadiatorSetOverride(!RadiatorGetOverride()); } |
andrewboyson | 0:3c04f4b47041 | 121 | |
andrewboyson | 0:3c04f4b47041 | 122 | int RadiatorInit() |
andrewboyson | 0:3c04f4b47041 | 123 | { |
andrewboyson | 48:6eac12df3ad5 | 124 | hallRom = DS18B20Roms + 8 * DS18B20RomCount; |
andrewboyson | 48:6eac12df3ad5 | 125 | DS18B20RomSetters[DS18B20RomCount] = setHallRom; |
andrewboyson | 48:6eac12df3ad5 | 126 | DS18B20RomNames[DS18B20RomCount] = "Hall"; |
andrewboyson | 48:6eac12df3ad5 | 127 | DS18B20RomCount++; |
andrewboyson | 48:6eac12df3ad5 | 128 | |
andrewboyson | 0:3c04f4b47041 | 129 | int address; |
andrewboyson | 96:18a3813bb4b5 | 130 | int8_t def1; |
andrewboyson | 95:97621bfbedfa | 131 | int16_t def2; |
andrewboyson | 96:18a3813bb4b5 | 132 | def1 = 0; address = FramLoad( 1, &htgWinter, &def1); if (address < 0) return -1; iWinter = address; |
andrewboyson | 98:c75c959bcde3 | 133 | FramAllocate(1); //Spare byte |
andrewboyson | 96:18a3813bb4b5 | 134 | address = FramLoad( 8, hallRom, 0); if (address < 0) return -1; iHallRom = address; |
andrewboyson | 96:18a3813bb4b5 | 135 | def1 = 23; address = FramLoad( 1, &overrideCancelHour, &def1); if (address < 0) return -1; iOverrideCancelHour = address; |
andrewboyson | 96:18a3813bb4b5 | 136 | def1 = 0; address = FramLoad( 1, &overrideCancelMinute, &def1); if (address < 0) return -1; iOverrideCancelMinute = address; |
andrewboyson | 98:c75c959bcde3 | 137 | FramAllocate(2); //Spare two bytes |
andrewboyson | 96:18a3813bb4b5 | 138 | def2 = 15; address = FramLoad( 2, &nightTemperature, &def2); if (address < 0) return -1; iNightTemperature = address; |
andrewboyson | 96:18a3813bb4b5 | 139 | def2 = 8; address = FramLoad( 2, &frostTemperature, &def2); if (address < 0) return -1; iFrostTemperature = address; |
andrewboyson | 0:3c04f4b47041 | 140 | |
andrewboyson | 5:82197a6997fd | 141 | RADIATOR_PUMP_DIR = 1; //Set the direction to 1 == output |
andrewboyson | 0:3c04f4b47041 | 142 | |
andrewboyson | 0:3c04f4b47041 | 143 | return 0; |
andrewboyson | 0:3c04f4b47041 | 144 | } |
andrewboyson | 0:3c04f4b47041 | 145 | void RadiatorMain() |
andrewboyson | 0:3c04f4b47041 | 146 | { |
andrewboyson | 0:3c04f4b47041 | 147 | //Make the radiator output |
andrewboyson | 0:3c04f4b47041 | 148 | makeOutputBeforeOverride(); |
andrewboyson | 99:84c3273dc77f | 149 | autoCancelOverride(); //Do this after making the output as it uses that information |
andrewboyson | 0:3c04f4b47041 | 150 | makeOutputWithOverride(); |
andrewboyson | 0:3c04f4b47041 | 151 | |
andrewboyson | 0:3c04f4b47041 | 152 | //Pump output |
andrewboyson | 5:82197a6997fd | 153 | if (RadiatorPump) RADIATOR_PUMP_SET; |
andrewboyson | 5:82197a6997fd | 154 | else RADIATOR_PUMP_CLR; |
andrewboyson | 0:3c04f4b47041 | 155 | |
andrewboyson | 0:3c04f4b47041 | 156 | } |