Controls the central heating system and the lights.
Dependencies: 1-wire clock crypto fram log lpc1768 net web wiz mbed
heating/boiler.c@6:0164a06f25e7, 2021-06-09 (annotated)
- Committer:
- andrewboyson
- Date:
- Wed Jun 09 09:25:03 2021 +0000
- Revision:
- 6:0164a06f25e7
- Parent:
- 3:f1464bf461c1
- Child:
- 7:e55c6a61e15b
Activated the boiler call disable if delta t is outside of the window.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
andrewboyson | 0:22b158d3c76f | 1 | #include <string.h> |
andrewboyson | 0:22b158d3c76f | 2 | #include <stdint.h> |
andrewboyson | 0:22b158d3c76f | 3 | #include <stdbool.h> |
andrewboyson | 0:22b158d3c76f | 4 | |
andrewboyson | 0:22b158d3c76f | 5 | #include "gpio.h" |
andrewboyson | 0:22b158d3c76f | 6 | #include "mstimer.h" |
andrewboyson | 0:22b158d3c76f | 7 | #include "ds18b20.h" |
andrewboyson | 3:f1464bf461c1 | 8 | #include "settings.h" |
andrewboyson | 0:22b158d3c76f | 9 | #include "pwm.h" |
andrewboyson | 0:22b158d3c76f | 10 | #include "log.h" |
andrewboyson | 0:22b158d3c76f | 11 | |
andrewboyson | 0:22b158d3c76f | 12 | #define BOILER_PUMP_DIR FIO2DIR(4) // P2.4 == p22 |
andrewboyson | 0:22b158d3c76f | 13 | #define BOILER_PUMP_PIN FIO2PIN(4) |
andrewboyson | 0:22b158d3c76f | 14 | #define BOILER_PUMP_SET FIO2SET(4) |
andrewboyson | 0:22b158d3c76f | 15 | #define BOILER_PUMP_CLR FIO2CLR(4) |
andrewboyson | 0:22b158d3c76f | 16 | |
andrewboyson | 0:22b158d3c76f | 17 | #define BOILER_CALL_DIR FIO2DIR(5) // P2.5 == p21 |
andrewboyson | 0:22b158d3c76f | 18 | #define BOILER_CALL_PIN FIO2PIN(5) |
andrewboyson | 0:22b158d3c76f | 19 | #define BOILER_CALL_SET FIO2SET(5) |
andrewboyson | 0:22b158d3c76f | 20 | #define BOILER_CALL_CLR FIO2CLR(5) |
andrewboyson | 0:22b158d3c76f | 21 | |
andrewboyson | 0:22b158d3c76f | 22 | #define PUMP_SPEED_CALLING_AUTO_ONLY -1 |
andrewboyson | 0:22b158d3c76f | 23 | #define PUMP_SPEED_CALLING_AUTO_TWEAK -2 |
andrewboyson | 0:22b158d3c76f | 24 | |
andrewboyson | 0:22b158d3c76f | 25 | #define MAX_SPEED 100 |
andrewboyson | 0:22b158d3c76f | 26 | |
andrewboyson | 3:f1464bf461c1 | 27 | static char* tankRom; |
andrewboyson | 3:f1464bf461c1 | 28 | static char* outputRom; |
andrewboyson | 3:f1464bf461c1 | 29 | static char* returnRom; |
andrewboyson | 0:22b158d3c76f | 30 | |
andrewboyson | 3:f1464bf461c1 | 31 | static int8_t fullSpeedSecs; |
andrewboyson | 0:22b158d3c76f | 32 | |
andrewboyson | 3:f1464bf461c1 | 33 | static int8_t tankSetPoint; |
andrewboyson | 3:f1464bf461c1 | 34 | static int16_t tankHysteresis; |
andrewboyson | 3:f1464bf461c1 | 35 | static int16_t _runOnDelta16ths; |
andrewboyson | 3:f1464bf461c1 | 36 | static uint8_t runOnTime2s; |
andrewboyson | 0:22b158d3c76f | 37 | |
andrewboyson | 3:f1464bf461c1 | 38 | static int8_t pumpSpeedCalling; |
andrewboyson | 3:f1464bf461c1 | 39 | static int8_t _rampDownTime; |
andrewboyson | 3:f1464bf461c1 | 40 | static int8_t boilerTarget; |
andrewboyson | 0:22b158d3c76f | 41 | |
andrewboyson | 3:f1464bf461c1 | 42 | static int8_t _minSpeed; |
andrewboyson | 3:f1464bf461c1 | 43 | static int8_t _midSpeedPwm; |
andrewboyson | 3:f1464bf461c1 | 44 | static int16_t _fullSpeedDeltaT16ths; |
andrewboyson | 0:22b158d3c76f | 45 | |
andrewboyson | 0:22b158d3c76f | 46 | //Set in main scan |
andrewboyson | 0:22b158d3c76f | 47 | static int16_t _boilerOutput16ths = DS18B20_ERROR_VALUE_NOT_SET; |
andrewboyson | 0:22b158d3c76f | 48 | static int16_t _boilerReturn16ths = DS18B20_ERROR_VALUE_NOT_SET; |
andrewboyson | 0:22b158d3c76f | 49 | static int16_t _boilerRtnDel16ths = DS18B20_ERROR_VALUE_NOT_SET; |
andrewboyson | 0:22b158d3c76f | 50 | static int16_t _boilerDeltaT16ths = DS18B20_ERROR_VALUE_NOT_SET; |
andrewboyson | 0:22b158d3c76f | 51 | static bool _boilerDeltaTisValid = false; |
andrewboyson | 0:22b158d3c76f | 52 | |
andrewboyson | 0:22b158d3c76f | 53 | int16_t BoilerGetTankDS18B20Value () { return DS18B20ValueFromRom(tankRom); } |
andrewboyson | 0:22b158d3c76f | 54 | int16_t BoilerGetOutputDS18B20Value() { return _boilerOutput16ths; } |
andrewboyson | 0:22b158d3c76f | 55 | int16_t BoilerGetReturnDS18B20Value() { return _boilerReturn16ths; } |
andrewboyson | 0:22b158d3c76f | 56 | int16_t BoilerGetRtnDelDS18B20Value() { return _boilerRtnDel16ths; } |
andrewboyson | 0:22b158d3c76f | 57 | int16_t BoilerGetDeltaTDS18B20Value() { return _boilerDeltaT16ths; } |
andrewboyson | 0:22b158d3c76f | 58 | int BoilerGetFullSpeedSecs () { return fullSpeedSecs; } |
andrewboyson | 0:22b158d3c76f | 59 | int BoilerGetTankSetPoint () { return tankSetPoint; } |
andrewboyson | 0:22b158d3c76f | 60 | int BoilerGetTankHysteresis () { return tankHysteresis; } |
andrewboyson | 0:22b158d3c76f | 61 | int BoilerGetRunOnDeltaT () { return _runOnDelta16ths; } |
andrewboyson | 0:22b158d3c76f | 62 | int BoilerGetRunOnTime () { return runOnTime2s << 1; } |
andrewboyson | 0:22b158d3c76f | 63 | int BoilerGetPumpSpeedCalling () { return pumpSpeedCalling; } |
andrewboyson | 3:f1464bf461c1 | 64 | int BoilerGetRampDownTime () { return _rampDownTime; } |
andrewboyson | 0:22b158d3c76f | 65 | int BoilerGetOutputTarget () { return boilerTarget; } |
andrewboyson | 0:22b158d3c76f | 66 | int BoilerGetMinSpeed () { return _minSpeed; } |
andrewboyson | 0:22b158d3c76f | 67 | int BoilerGetMidSpeedPwm () { return _midSpeedPwm; } |
andrewboyson | 0:22b158d3c76f | 68 | int BoilerGetFullSpeedDeltaT () { return _fullSpeedDeltaT16ths; } |
andrewboyson | 0:22b158d3c76f | 69 | |
andrewboyson | 3:f1464bf461c1 | 70 | static void setTankRom (char* value) { memcpy( tankRom, value, 8); SetTankRom ( tankRom ); } |
andrewboyson | 3:f1464bf461c1 | 71 | static void setOutputRom (char* value) { memcpy(outputRom, value, 8); SetOutputRom ( outputRom ); } |
andrewboyson | 3:f1464bf461c1 | 72 | static void setReturnRom (char* value) { memcpy(returnRom, value, 8); SetReturnRom ( returnRom ); } |
andrewboyson | 3:f1464bf461c1 | 73 | void BoilerSetFullSpeedSecs (int value) { fullSpeedSecs = value; SetBoilerFullSpeedSecs (&fullSpeedSecs ); } |
andrewboyson | 3:f1464bf461c1 | 74 | void BoilerSetTankSetPoint (int value) { tankSetPoint = value; SetTankSetPoint (&tankSetPoint ); } |
andrewboyson | 3:f1464bf461c1 | 75 | void BoilerSetTankHysteresis (int value) { tankHysteresis = value; SetTankHysteresis (&tankHysteresis ); } |
andrewboyson | 3:f1464bf461c1 | 76 | void BoilerSetRunOnDeltaT (int value) { _runOnDelta16ths = value; SetBoilerRunOnDeltaT (&_runOnDelta16ths ); } |
andrewboyson | 3:f1464bf461c1 | 77 | void BoilerSetRunOnTime (int value) { runOnTime2s = value >> 1; SetBoilerRunOnTime2s (&runOnTime2s ); } |
andrewboyson | 3:f1464bf461c1 | 78 | void BoilerSetPumpSpeedCalling (int value) { pumpSpeedCalling = value; SetBoilerPumpSpeedCalling(&pumpSpeedCalling ); } |
andrewboyson | 3:f1464bf461c1 | 79 | void BoilerSetRampDownTime (int value) { _rampDownTime = value; SetBoilerRampDownTime (&_rampDownTime ); } |
andrewboyson | 3:f1464bf461c1 | 80 | void BoilerSetOutputTarget (int value) { boilerTarget = value; SetBoilerTarget (&boilerTarget ); } |
andrewboyson | 3:f1464bf461c1 | 81 | void BoilerSetMinSpeed (int value) { _minSpeed = value; SetBoilerMinSpeed (&_minSpeed ); } |
andrewboyson | 3:f1464bf461c1 | 82 | void BoilerSetMidSpeedPwm (int value) { _midSpeedPwm = value; SetBoilerMidSpeedPwm (&_midSpeedPwm ); } |
andrewboyson | 3:f1464bf461c1 | 83 | void BoilerSetFullSpeedDeltaT (int value) { _fullSpeedDeltaT16ths = value; SetBoilerFullSpeedDeltaT (&_fullSpeedDeltaT16ths); } |
andrewboyson | 0:22b158d3c76f | 84 | |
andrewboyson | 0:22b158d3c76f | 85 | static int calculateBetweenTwoPoints(int x, int xA, int xB, int yA, int yB) |
andrewboyson | 0:22b158d3c76f | 86 | { |
andrewboyson | 0:22b158d3c76f | 87 | float m = (float)(yB - yA) / (xB - xA); |
andrewboyson | 0:22b158d3c76f | 88 | return yA + m * (x - xA); |
andrewboyson | 0:22b158d3c76f | 89 | } |
andrewboyson | 0:22b158d3c76f | 90 | static int calculateSpeedFromDeltaT(int deltaT16ths) |
andrewboyson | 0:22b158d3c76f | 91 | { |
andrewboyson | 0:22b158d3c76f | 92 | if (deltaT16ths < _fullSpeedDeltaT16ths) return MAX_SPEED; //Needed in case deltaT16ths is negative or zero |
andrewboyson | 0:22b158d3c76f | 93 | int speed = MAX_SPEED * _fullSpeedDeltaT16ths / deltaT16ths; //eg for 20 deg ==> 100 * (10 << 4) / (20 << 4) == 50 |
andrewboyson | 0:22b158d3c76f | 94 | if (speed > MAX_SPEED) speed = MAX_SPEED; |
andrewboyson | 0:22b158d3c76f | 95 | if (speed < _minSpeed) speed = _minSpeed; |
andrewboyson | 0:22b158d3c76f | 96 | return speed; |
andrewboyson | 0:22b158d3c76f | 97 | } |
andrewboyson | 0:22b158d3c76f | 98 | static int calculateDeltaTFromSpeed(int speed) |
andrewboyson | 0:22b158d3c76f | 99 | { |
andrewboyson | 0:22b158d3c76f | 100 | int deltaT16ths = MAX_SPEED * _fullSpeedDeltaT16ths / speed; //eg for speed = 50 ==> 100 * (10 << 4) / 50 == 20 << 4 |
andrewboyson | 0:22b158d3c76f | 101 | return deltaT16ths; |
andrewboyson | 0:22b158d3c76f | 102 | } |
andrewboyson | 0:22b158d3c76f | 103 | |
andrewboyson | 0:22b158d3c76f | 104 | int BoilerInit() |
andrewboyson | 0:22b158d3c76f | 105 | { |
andrewboyson | 0:22b158d3c76f | 106 | tankRom = DS18B20Roms + 8 * DS18B20RomCount; |
andrewboyson | 0:22b158d3c76f | 107 | DS18B20RomSetters[DS18B20RomCount] = setTankRom; |
andrewboyson | 0:22b158d3c76f | 108 | DS18B20RomNames[DS18B20RomCount] = "Tank"; |
andrewboyson | 0:22b158d3c76f | 109 | DS18B20RomCount++; |
andrewboyson | 0:22b158d3c76f | 110 | |
andrewboyson | 0:22b158d3c76f | 111 | outputRom = DS18B20Roms + 8 * DS18B20RomCount; |
andrewboyson | 0:22b158d3c76f | 112 | DS18B20RomSetters[DS18B20RomCount] = setOutputRom; |
andrewboyson | 0:22b158d3c76f | 113 | DS18B20RomNames[DS18B20RomCount] = "BlrOut"; |
andrewboyson | 0:22b158d3c76f | 114 | DS18B20RomCount++; |
andrewboyson | 0:22b158d3c76f | 115 | |
andrewboyson | 0:22b158d3c76f | 116 | returnRom = DS18B20Roms + 8 * DS18B20RomCount; |
andrewboyson | 0:22b158d3c76f | 117 | DS18B20RomSetters[DS18B20RomCount] = setReturnRom; |
andrewboyson | 0:22b158d3c76f | 118 | DS18B20RomNames[DS18B20RomCount] = "BlrRtn"; |
andrewboyson | 0:22b158d3c76f | 119 | DS18B20RomCount++; |
andrewboyson | 0:22b158d3c76f | 120 | |
andrewboyson | 0:22b158d3c76f | 121 | int address; |
andrewboyson | 0:22b158d3c76f | 122 | uint8_t def1; |
andrewboyson | 0:22b158d3c76f | 123 | int16_t def2; |
andrewboyson | 0:22b158d3c76f | 124 | int32_t def4; |
andrewboyson | 3:f1464bf461c1 | 125 | GetTankRom ( tankRom ); |
andrewboyson | 3:f1464bf461c1 | 126 | GetOutputRom ( outputRom ); |
andrewboyson | 3:f1464bf461c1 | 127 | GetReturnRom ( returnRom ); |
andrewboyson | 3:f1464bf461c1 | 128 | GetBoilerFullSpeedSecs (&fullSpeedSecs ); |
andrewboyson | 3:f1464bf461c1 | 129 | GetTankSetPoint (&tankSetPoint ); |
andrewboyson | 3:f1464bf461c1 | 130 | GetTankHysteresis (&tankHysteresis ); |
andrewboyson | 3:f1464bf461c1 | 131 | GetBoilerRunOnDeltaT (&_runOnDelta16ths ); |
andrewboyson | 3:f1464bf461c1 | 132 | GetBoilerRunOnTime2s (&runOnTime2s ); |
andrewboyson | 3:f1464bf461c1 | 133 | GetBoilerPumpSpeedCalling(&pumpSpeedCalling ); |
andrewboyson | 3:f1464bf461c1 | 134 | GetBoilerRampDownTime (&_rampDownTime ); |
andrewboyson | 3:f1464bf461c1 | 135 | GetBoilerTarget (&boilerTarget ); |
andrewboyson | 3:f1464bf461c1 | 136 | GetBoilerMinSpeed (&_minSpeed ); |
andrewboyson | 3:f1464bf461c1 | 137 | GetBoilerMidSpeedPwm (&_midSpeedPwm ); |
andrewboyson | 3:f1464bf461c1 | 138 | GetBoilerFullSpeedDeltaT (&_fullSpeedDeltaT16ths); |
andrewboyson | 0:22b158d3c76f | 139 | |
andrewboyson | 0:22b158d3c76f | 140 | BOILER_PUMP_DIR = 1; //Set the direction to 1 == output |
andrewboyson | 0:22b158d3c76f | 141 | BOILER_CALL_DIR = 1; //Set the direction to 1 == output |
andrewboyson | 0:22b158d3c76f | 142 | |
andrewboyson | 0:22b158d3c76f | 143 | PwmInit(400, 100); |
andrewboyson | 0:22b158d3c76f | 144 | |
andrewboyson | 0:22b158d3c76f | 145 | return 0; |
andrewboyson | 0:22b158d3c76f | 146 | } |
andrewboyson | 0:22b158d3c76f | 147 | bool BoilerCallEnable = true; |
andrewboyson | 0:22b158d3c76f | 148 | bool BoilerCall = false; |
andrewboyson | 0:22b158d3c76f | 149 | static void controlBoilerCall() |
andrewboyson | 0:22b158d3c76f | 150 | { |
andrewboyson | 0:22b158d3c76f | 151 | if (BoilerCallEnable) |
andrewboyson | 0:22b158d3c76f | 152 | { |
andrewboyson | 0:22b158d3c76f | 153 | int tankTemp16ths = DS18B20ValueFromRom(tankRom); |
andrewboyson | 0:22b158d3c76f | 154 | if (DS18B20IsValidValue(tankTemp16ths)) //Ignore values which are likely to be wrong |
andrewboyson | 0:22b158d3c76f | 155 | { |
andrewboyson | 0:22b158d3c76f | 156 | int tankUpper16ths = tankSetPoint << 4; |
andrewboyson | 0:22b158d3c76f | 157 | int hysteresis16ths = tankHysteresis << 4; |
andrewboyson | 0:22b158d3c76f | 158 | int tankLower16ths = tankUpper16ths - hysteresis16ths; |
andrewboyson | 0:22b158d3c76f | 159 | |
andrewboyson | 0:22b158d3c76f | 160 | if (tankTemp16ths >= tankUpper16ths) BoilerCall = false; |
andrewboyson | 0:22b158d3c76f | 161 | if (tankTemp16ths <= tankLower16ths) BoilerCall = true; |
andrewboyson | 0:22b158d3c76f | 162 | } |
andrewboyson | 0:22b158d3c76f | 163 | } |
andrewboyson | 0:22b158d3c76f | 164 | else |
andrewboyson | 0:22b158d3c76f | 165 | { |
andrewboyson | 0:22b158d3c76f | 166 | BoilerCall = false; |
andrewboyson | 0:22b158d3c76f | 167 | } |
andrewboyson | 0:22b158d3c76f | 168 | } |
andrewboyson | 0:22b158d3c76f | 169 | bool BoilerPump = false; |
andrewboyson | 0:22b158d3c76f | 170 | static void controlBoilerPump() |
andrewboyson | 0:22b158d3c76f | 171 | { |
andrewboyson | 0:22b158d3c76f | 172 | static uint32_t msTimerBoilerPumpRunOn = 0; |
andrewboyson | 0:22b158d3c76f | 173 | if (BoilerCall) |
andrewboyson | 0:22b158d3c76f | 174 | { |
andrewboyson | 0:22b158d3c76f | 175 | BoilerPump = true; |
andrewboyson | 0:22b158d3c76f | 176 | msTimerBoilerPumpRunOn = MsTimerCount; |
andrewboyson | 0:22b158d3c76f | 177 | } |
andrewboyson | 0:22b158d3c76f | 178 | else |
andrewboyson | 0:22b158d3c76f | 179 | { |
andrewboyson | 0:22b158d3c76f | 180 | if (MsTimerRelative(msTimerBoilerPumpRunOn, runOnTime2s * 2000)) BoilerPump = false; |
andrewboyson | 0:22b158d3c76f | 181 | if (_boilerDeltaTisValid && _boilerDeltaT16ths < _runOnDelta16ths ) BoilerPump = false; |
andrewboyson | 0:22b158d3c76f | 182 | } |
andrewboyson | 0:22b158d3c76f | 183 | } |
andrewboyson | 0:22b158d3c76f | 184 | int BoilerPumpFlow = MAX_SPEED; |
andrewboyson | 0:22b158d3c76f | 185 | int BoilerPumpSpeed = MAX_SPEED; |
andrewboyson | 0:22b158d3c76f | 186 | int BoilerPumpPwm = 0; |
andrewboyson | 0:22b158d3c76f | 187 | static int _autoSpeed = 0; |
andrewboyson | 0:22b158d3c76f | 188 | static void calculateAutoSpeed() |
andrewboyson | 0:22b158d3c76f | 189 | { |
andrewboyson | 0:22b158d3c76f | 190 | if (!DS18B20IsValidValue(_boilerReturn16ths)) return; |
andrewboyson | 0:22b158d3c76f | 191 | |
andrewboyson | 0:22b158d3c76f | 192 | int target16ths = (int)boilerTarget << 4; |
andrewboyson | 0:22b158d3c76f | 193 | int targetRise16ths = target16ths - _boilerReturn16ths; //eg 65 - eg 45 = 20*16 16ths |
andrewboyson | 0:22b158d3c76f | 194 | |
andrewboyson | 0:22b158d3c76f | 195 | _autoSpeed = calculateSpeedFromDeltaT(targetRise16ths); |
andrewboyson | 0:22b158d3c76f | 196 | } |
andrewboyson | 0:22b158d3c76f | 197 | static void controlBoilerPumpSpeed() |
andrewboyson | 0:22b158d3c76f | 198 | { |
andrewboyson | 0:22b158d3c76f | 199 | static uint32_t msTimerReduction = 0; |
andrewboyson | 0:22b158d3c76f | 200 | calculateAutoSpeed(); |
andrewboyson | 0:22b158d3c76f | 201 | if (BoilerCall) |
andrewboyson | 0:22b158d3c76f | 202 | { |
andrewboyson | 0:22b158d3c76f | 203 | if (pumpSpeedCalling < 0) BoilerPumpSpeed = _autoSpeed; //Auto |
andrewboyson | 0:22b158d3c76f | 204 | else BoilerPumpSpeed = pumpSpeedCalling; //Manual |
andrewboyson | 0:22b158d3c76f | 205 | msTimerReduction = MsTimerCount; |
andrewboyson | 0:22b158d3c76f | 206 | } |
andrewboyson | 0:22b158d3c76f | 207 | else |
andrewboyson | 0:22b158d3c76f | 208 | { |
andrewboyson | 0:22b158d3c76f | 209 | if (BoilerPumpSpeed > _minSpeed) |
andrewboyson | 0:22b158d3c76f | 210 | { |
andrewboyson | 0:22b158d3c76f | 211 | int msPerUnit = 1000 * _rampDownTime / (MAX_SPEED - _minSpeed); |
andrewboyson | 0:22b158d3c76f | 212 | if (MsTimerRepetitive(&msTimerReduction, msPerUnit)) BoilerPumpSpeed--; |
andrewboyson | 0:22b158d3c76f | 213 | } |
andrewboyson | 0:22b158d3c76f | 214 | else |
andrewboyson | 0:22b158d3c76f | 215 | { |
andrewboyson | 0:22b158d3c76f | 216 | BoilerPumpSpeed = _minSpeed; |
andrewboyson | 0:22b158d3c76f | 217 | } |
andrewboyson | 0:22b158d3c76f | 218 | } |
andrewboyson | 0:22b158d3c76f | 219 | if (BoilerPumpSpeed < _minSpeed) BoilerPumpSpeed = _minSpeed; |
andrewboyson | 0:22b158d3c76f | 220 | if (BoilerPumpSpeed > MAX_SPEED) BoilerPumpSpeed = MAX_SPEED; |
andrewboyson | 0:22b158d3c76f | 221 | } |
andrewboyson | 0:22b158d3c76f | 222 | static int speedToPwm(int speed) |
andrewboyson | 0:22b158d3c76f | 223 | { |
andrewboyson | 0:22b158d3c76f | 224 | #define MAX_SPEED_PWM 10 |
andrewboyson | 0:22b158d3c76f | 225 | #define MIN_SPEED_PWM 84 |
andrewboyson | 0:22b158d3c76f | 226 | /* |
andrewboyson | 0:22b158d3c76f | 227 | PWM input signal [%] Pump status |
andrewboyson | 0:22b158d3c76f | 228 | ≤ 10 Maximum speed |
andrewboyson | 0:22b158d3c76f | 229 | > 10 / ≤ 84 Variable speed from minimum to maximum |
andrewboyson | 0:22b158d3c76f | 230 | speed |
andrewboyson | 0:22b158d3c76f | 231 | > 84 / ≤ 91 Minimum speed |
andrewboyson | 0:22b158d3c76f | 232 | > 91/95 Hysteresis area: on/off |
andrewboyson | 0:22b158d3c76f | 233 | > 95 / ≤ 100 Standby mode: off |
andrewboyson | 0:22b158d3c76f | 234 | |
andrewboyson | 0:22b158d3c76f | 235 | Max speed 100 is at fitted = 74; pwm = 10 |
andrewboyson | 0:22b158d3c76f | 236 | Min speed 0 is at fitted = 0; pwm = 84 |
andrewboyson | 0:22b158d3c76f | 237 | */ |
andrewboyson | 0:22b158d3c76f | 238 | if (speed <= _minSpeed) return MIN_SPEED_PWM; |
andrewboyson | 0:22b158d3c76f | 239 | if (speed >= MAX_SPEED) return MAX_SPEED_PWM; |
andrewboyson | 0:22b158d3c76f | 240 | int midSpeed = (_minSpeed + MAX_SPEED) / 2; |
andrewboyson | 0:22b158d3c76f | 241 | if (speed < midSpeed) return calculateBetweenTwoPoints(speed, _minSpeed, midSpeed, MIN_SPEED_PWM, _midSpeedPwm); |
andrewboyson | 0:22b158d3c76f | 242 | else return calculateBetweenTwoPoints(speed, midSpeed, MAX_SPEED, _midSpeedPwm, MAX_SPEED_PWM); |
andrewboyson | 0:22b158d3c76f | 243 | //int pwm = calculateBetweenTwoPoints(BoilerPumpSpeed, _minSpeed, MAX_SPEED, 84, 10); |
andrewboyson | 0:22b158d3c76f | 244 | //if (pwm < 10) pwm = 10; |
andrewboyson | 0:22b158d3c76f | 245 | //if (pwm > 84) pwm = 84; |
andrewboyson | 0:22b158d3c76f | 246 | //BoilerPumpPwm = pwm; |
andrewboyson | 0:22b158d3c76f | 247 | } |
andrewboyson | 0:22b158d3c76f | 248 | #define TIME_BEFORE_TWEAK_SECS 120 |
andrewboyson | 0:22b158d3c76f | 249 | static void tweakDeltaTs() |
andrewboyson | 0:22b158d3c76f | 250 | { |
andrewboyson | 0:22b158d3c76f | 251 | if (pumpSpeedCalling != PUMP_SPEED_CALLING_AUTO_TWEAK) return; |
andrewboyson | 0:22b158d3c76f | 252 | |
andrewboyson | 0:22b158d3c76f | 253 | static uint32_t msTimerBoilerHeating = 0; |
andrewboyson | 0:22b158d3c76f | 254 | if (!BoilerCall) msTimerBoilerHeating = MsTimerCount; |
andrewboyson | 0:22b158d3c76f | 255 | if (!MsTimerRelative(msTimerBoilerHeating, TIME_BEFORE_TWEAK_SECS * 1000)) return; |
andrewboyson | 0:22b158d3c76f | 256 | |
andrewboyson | 0:22b158d3c76f | 257 | if (!_boilerDeltaTisValid) return; |
andrewboyson | 0:22b158d3c76f | 258 | |
andrewboyson | 0:22b158d3c76f | 259 | static int speedLastScan = -1; |
andrewboyson | 0:22b158d3c76f | 260 | |
andrewboyson | 0:22b158d3c76f | 261 | if (speedLastScan < MAX_SPEED && BoilerPumpSpeed == MAX_SPEED) |
andrewboyson | 0:22b158d3c76f | 262 | { |
andrewboyson | 0:22b158d3c76f | 263 | if (_fullSpeedDeltaT16ths > _boilerDeltaT16ths) _fullSpeedDeltaT16ths--; |
andrewboyson | 0:22b158d3c76f | 264 | if (_fullSpeedDeltaT16ths < _boilerDeltaT16ths) _fullSpeedDeltaT16ths++; |
andrewboyson | 0:22b158d3c76f | 265 | } |
andrewboyson | 0:22b158d3c76f | 266 | |
andrewboyson | 0:22b158d3c76f | 267 | speedLastScan = BoilerPumpSpeed; |
andrewboyson | 0:22b158d3c76f | 268 | } |
andrewboyson | 0:22b158d3c76f | 269 | |
andrewboyson | 0:22b158d3c76f | 270 | #define TIME_BEFORE_DELTA_T_ALARM_SECS 300 |
andrewboyson | 6:0164a06f25e7 | 271 | #define DELTA_T_LIMIT 3 |
andrewboyson | 0:22b158d3c76f | 272 | static void checkDeltaTs() |
andrewboyson | 0:22b158d3c76f | 273 | { |
andrewboyson | 0:22b158d3c76f | 274 | static uint32_t msTimerDeltaTNonConform = 0; |
andrewboyson | 0:22b158d3c76f | 275 | if (!BoilerCall) |
andrewboyson | 0:22b158d3c76f | 276 | { |
andrewboyson | 0:22b158d3c76f | 277 | msTimerDeltaTNonConform = MsTimerCount; |
andrewboyson | 0:22b158d3c76f | 278 | return; |
andrewboyson | 0:22b158d3c76f | 279 | } |
andrewboyson | 0:22b158d3c76f | 280 | |
andrewboyson | 0:22b158d3c76f | 281 | int expectedDeltaT16ths = calculateDeltaTFromSpeed(BoilerPumpSpeed); |
andrewboyson | 0:22b158d3c76f | 282 | |
andrewboyson | 0:22b158d3c76f | 283 | bool deltaTisOk = _boilerDeltaTisValid && |
andrewboyson | 6:0164a06f25e7 | 284 | _boilerDeltaT16ths > (expectedDeltaT16ths - (DELTA_T_LIMIT << 4)) && |
andrewboyson | 6:0164a06f25e7 | 285 | _boilerDeltaT16ths < (expectedDeltaT16ths + (DELTA_T_LIMIT << 4)); |
andrewboyson | 0:22b158d3c76f | 286 | |
andrewboyson | 0:22b158d3c76f | 287 | static bool hadAlarm = false; |
andrewboyson | 0:22b158d3c76f | 288 | if (deltaTisOk) msTimerDeltaTNonConform = MsTimerCount; |
andrewboyson | 0:22b158d3c76f | 289 | bool haveAlarm = MsTimerRelative(msTimerDeltaTNonConform, TIME_BEFORE_DELTA_T_ALARM_SECS * 1000); |
andrewboyson | 0:22b158d3c76f | 290 | if (haveAlarm && !hadAlarm) |
andrewboyson | 0:22b158d3c76f | 291 | { |
andrewboyson | 6:0164a06f25e7 | 292 | BoilerCallEnable = false; |
andrewboyson | 6:0164a06f25e7 | 293 | LogTimeF("Boiler disabled - delta T was outside %d degree window for %d seconds", DELTA_T_LIMIT, TIME_BEFORE_DELTA_T_ALARM_SECS); |
andrewboyson | 6:0164a06f25e7 | 294 | Log(": actual "); |
andrewboyson | 6:0164a06f25e7 | 295 | DS18B20Log(_boilerDeltaT16ths); |
andrewboyson | 6:0164a06f25e7 | 296 | Log(", expected "); |
andrewboyson | 6:0164a06f25e7 | 297 | DS18B20Log(expectedDeltaT16ths); |
andrewboyson | 6:0164a06f25e7 | 298 | Log("\r\n"); |
andrewboyson | 0:22b158d3c76f | 299 | } |
andrewboyson | 0:22b158d3c76f | 300 | hadAlarm = haveAlarm; |
andrewboyson | 0:22b158d3c76f | 301 | } |
andrewboyson | 0:22b158d3c76f | 302 | #define NUMBER_OF_STEPS 10 |
andrewboyson | 0:22b158d3c76f | 303 | static int16_t _returns16ths[NUMBER_OF_STEPS]; //0 is last, 9th is first |
andrewboyson | 0:22b158d3c76f | 304 | static void delayLine() |
andrewboyson | 0:22b158d3c76f | 305 | { |
andrewboyson | 0:22b158d3c76f | 306 | static uint32_t msTimerDelay = 0; |
andrewboyson | 0:22b158d3c76f | 307 | if (BoilerPump) |
andrewboyson | 0:22b158d3c76f | 308 | { |
andrewboyson | 0:22b158d3c76f | 309 | int msTotal = 1000 * fullSpeedSecs * MAX_SPEED / BoilerPumpSpeed; //speed 10 ==> 10000; speed 100 ==> 1000 |
andrewboyson | 0:22b158d3c76f | 310 | int msPerStep = msTotal / NUMBER_OF_STEPS; |
andrewboyson | 0:22b158d3c76f | 311 | if (MsTimerRelative(msTimerDelay, msPerStep)) |
andrewboyson | 0:22b158d3c76f | 312 | { |
andrewboyson | 0:22b158d3c76f | 313 | for (int i = 0; i < NUMBER_OF_STEPS - 1; i++) _returns16ths[i] = _returns16ths[i + 1]; |
andrewboyson | 0:22b158d3c76f | 314 | _returns16ths[NUMBER_OF_STEPS - 1] = _boilerReturn16ths; |
andrewboyson | 0:22b158d3c76f | 315 | msTimerDelay = MsTimerCount; |
andrewboyson | 0:22b158d3c76f | 316 | //LogTimeF("Ms per step = %d, delayed boiler return = ", msPerStep); |
andrewboyson | 0:22b158d3c76f | 317 | //DS18B20Log(_returns16ths[0]); |
andrewboyson | 0:22b158d3c76f | 318 | //Log("\r\n"); |
andrewboyson | 0:22b158d3c76f | 319 | } |
andrewboyson | 0:22b158d3c76f | 320 | } |
andrewboyson | 0:22b158d3c76f | 321 | else |
andrewboyson | 0:22b158d3c76f | 322 | { |
andrewboyson | 0:22b158d3c76f | 323 | msTimerDelay = MsTimerCount; |
andrewboyson | 0:22b158d3c76f | 324 | for (int i = 0; i < NUMBER_OF_STEPS; i++) _returns16ths[i] = DS18B20_ERROR_VALUE_NOT_SET; |
andrewboyson | 0:22b158d3c76f | 325 | } |
andrewboyson | 0:22b158d3c76f | 326 | } |
andrewboyson | 0:22b158d3c76f | 327 | |
andrewboyson | 0:22b158d3c76f | 328 | void BoilerMain() |
andrewboyson | 0:22b158d3c76f | 329 | { |
andrewboyson | 0:22b158d3c76f | 330 | delayLine(); |
andrewboyson | 0:22b158d3c76f | 331 | _boilerOutput16ths = DS18B20ValueFromRom(outputRom); |
andrewboyson | 0:22b158d3c76f | 332 | _boilerReturn16ths = DS18B20ValueFromRom(returnRom); |
andrewboyson | 0:22b158d3c76f | 333 | _boilerRtnDel16ths = _returns16ths[0]; |
andrewboyson | 0:22b158d3c76f | 334 | _boilerDeltaTisValid = DS18B20IsValidValue(_boilerOutput16ths) && DS18B20IsValidValue(_boilerRtnDel16ths); |
andrewboyson | 0:22b158d3c76f | 335 | if (_boilerDeltaTisValid) _boilerDeltaT16ths = _boilerOutput16ths - _boilerRtnDel16ths; |
andrewboyson | 0:22b158d3c76f | 336 | else _boilerDeltaT16ths = DS18B20_ERROR_VALUE_NOT_SET; |
andrewboyson | 0:22b158d3c76f | 337 | |
andrewboyson | 0:22b158d3c76f | 338 | controlBoilerCall(); |
andrewboyson | 0:22b158d3c76f | 339 | if (BoilerCall) BOILER_CALL_SET; |
andrewboyson | 0:22b158d3c76f | 340 | else BOILER_CALL_CLR; |
andrewboyson | 0:22b158d3c76f | 341 | |
andrewboyson | 0:22b158d3c76f | 342 | controlBoilerPump(); |
andrewboyson | 0:22b158d3c76f | 343 | if (BoilerPump) BOILER_PUMP_SET; |
andrewboyson | 0:22b158d3c76f | 344 | else BOILER_PUMP_CLR; |
andrewboyson | 0:22b158d3c76f | 345 | |
andrewboyson | 0:22b158d3c76f | 346 | controlBoilerPumpSpeed(); |
andrewboyson | 0:22b158d3c76f | 347 | BoilerPumpPwm = speedToPwm(BoilerPumpSpeed); |
andrewboyson | 0:22b158d3c76f | 348 | PwmSet(BoilerPumpPwm); |
andrewboyson | 0:22b158d3c76f | 349 | |
andrewboyson | 0:22b158d3c76f | 350 | tweakDeltaTs(); |
andrewboyson | 0:22b158d3c76f | 351 | checkDeltaTs(); |
andrewboyson | 0:22b158d3c76f | 352 | } |