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:
Tue Feb 23 20:35:07 2021 +0000
Revision:
105:1899f7ed17ec
Parent:
104:46ce1aaf8be7
Child:
106:41ed3ea0bbba
Added ability to set the minimum flow rate and removed the correction to delta T relative to speed. Adding the round circuit time and linked to speed. Next task is to linearize the flow.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 0:3c04f4b47041 1 #include <string.h>
andrewboyson 0:3c04f4b47041 2 #include <stdint.h>
andrewboyson 0:3c04f4b47041 3 #include <stdbool.h>
andrewboyson 0:3c04f4b47041 4
andrewboyson 35:bb8a6d1c034c 5 #include "gpio.h"
andrewboyson 35:bb8a6d1c034c 6 #include "mstimer.h"
andrewboyson 1:ccc66fdf858d 7 #include "ds18b20.h"
andrewboyson 35:bb8a6d1c034c 8 #include "fram.h"
andrewboyson 104:46ce1aaf8be7 9 #include "pwm.h"
andrewboyson 104:46ce1aaf8be7 10 #include "log.h"
andrewboyson 0:3c04f4b47041 11
andrewboyson 5:82197a6997fd 12 #define BOILER_PUMP_DIR FIO2DIR(4) // P2.4 == p22
andrewboyson 5:82197a6997fd 13 #define BOILER_PUMP_PIN FIO2PIN(4)
andrewboyson 5:82197a6997fd 14 #define BOILER_PUMP_SET FIO2SET(4)
andrewboyson 5:82197a6997fd 15 #define BOILER_PUMP_CLR FIO2CLR(4)
andrewboyson 5:82197a6997fd 16
andrewboyson 5:82197a6997fd 17 #define BOILER_CALL_DIR FIO2DIR(5) // P2.5 == p21
andrewboyson 5:82197a6997fd 18 #define BOILER_CALL_PIN FIO2PIN(5)
andrewboyson 5:82197a6997fd 19 #define BOILER_CALL_SET FIO2SET(5)
andrewboyson 5:82197a6997fd 20 #define BOILER_CALL_CLR FIO2CLR(5)
andrewboyson 0:3c04f4b47041 21
andrewboyson 105:1899f7ed17ec 22 #define PUMP_SPEED_CALLING_AUTO_ONLY -1
andrewboyson 105:1899f7ed17ec 23 #define PUMP_SPEED_CALLING_AUTO_TWEAK -2
andrewboyson 105:1899f7ed17ec 24
andrewboyson 105:1899f7ed17ec 25 #define MIN_SPEED 40
andrewboyson 105:1899f7ed17ec 26 #define MAX_SPEED 100
andrewboyson 105:1899f7ed17ec 27
andrewboyson 48:6eac12df3ad5 28 static char* tankRom; static int iTankRom;
andrewboyson 48:6eac12df3ad5 29 static char* outputRom; static int iOutputRom;
andrewboyson 48:6eac12df3ad5 30 static char* returnRom; static int iReturnRom;
andrewboyson 0:3c04f4b47041 31
andrewboyson 105:1899f7ed17ec 32 static int8_t fullSpeedSecs; static int iFullSpeedSecs;
andrewboyson 105:1899f7ed17ec 33
andrewboyson 105:1899f7ed17ec 34 static int8_t tankSetPoint; static int iTankSetPoint;
andrewboyson 104:46ce1aaf8be7 35 static int16_t tankHysteresis; static int iTankHysteresis;
andrewboyson 104:46ce1aaf8be7 36 static int16_t runOnResidual16ths; static int iRunOnResidual;
andrewboyson 105:1899f7ed17ec 37 static uint8_t runOnTime2s; static int iRunOnTime;
andrewboyson 104:46ce1aaf8be7 38
andrewboyson 104:46ce1aaf8be7 39 static int8_t boilerTarget; static int iBoilerTarget;
andrewboyson 104:46ce1aaf8be7 40 static int8_t pumpSpeedCalling; static int iPumpSpeedCalling;
andrewboyson 104:46ce1aaf8be7 41 static int8_t pumpSpeedRunOn; static int iPumpSpeedRunOn;
andrewboyson 104:46ce1aaf8be7 42
andrewboyson 104:46ce1aaf8be7 43 static int16_t rise16thsAt0; static int iRiseAt0;
andrewboyson 104:46ce1aaf8be7 44 static int16_t rise16thsAt50; static int iRiseAt50;
andrewboyson 104:46ce1aaf8be7 45 static int16_t rise16thsAt100; static int iRiseAt100;
andrewboyson 0:3c04f4b47041 46
andrewboyson 105:1899f7ed17ec 47 //Set in main scan
andrewboyson 105:1899f7ed17ec 48 static int16_t _boilerOutput16ths = DS18B20_ERROR_VALUE_NOT_SET;
andrewboyson 105:1899f7ed17ec 49 static int16_t _boilerReturn16ths = DS18B20_ERROR_VALUE_NOT_SET;
andrewboyson 105:1899f7ed17ec 50 static int16_t _boilerRtnDel16ths = DS18B20_ERROR_VALUE_NOT_SET;
andrewboyson 105:1899f7ed17ec 51 static int16_t _boilerDeltaT16ths = DS18B20_ERROR_VALUE_NOT_SET;
andrewboyson 105:1899f7ed17ec 52 static bool _boilerDeltaTisValid = false;
andrewboyson 105:1899f7ed17ec 53
andrewboyson 105:1899f7ed17ec 54 int16_t BoilerGetTankDS18B20Value () { return DS18B20ValueFromRom(tankRom); }
andrewboyson 105:1899f7ed17ec 55 int16_t BoilerGetOutputDS18B20Value() { return _boilerOutput16ths; }
andrewboyson 105:1899f7ed17ec 56 int16_t BoilerGetReturnDS18B20Value() { return _boilerReturn16ths; }
andrewboyson 105:1899f7ed17ec 57 int16_t BoilerGetRtnDelDS18B20Value() { return _boilerRtnDel16ths; }
andrewboyson 105:1899f7ed17ec 58 int16_t BoilerGetDeltaTDS18B20Value() { return _boilerDeltaT16ths; }
andrewboyson 105:1899f7ed17ec 59 int BoilerGetFullSpeedSecs () { return fullSpeedSecs; }
andrewboyson 105:1899f7ed17ec 60 int BoilerGetTankSetPoint () { return tankSetPoint; }
andrewboyson 105:1899f7ed17ec 61 int BoilerGetTankHysteresis () { return tankHysteresis; }
andrewboyson 105:1899f7ed17ec 62 int BoilerGetRunOnDeltaT () { return runOnResidual16ths; }
andrewboyson 105:1899f7ed17ec 63 int BoilerGetRunOnTime () { return runOnTime2s << 1; }
andrewboyson 105:1899f7ed17ec 64 int BoilerGetPumpSpeedCalling () { return pumpSpeedCalling; }
andrewboyson 105:1899f7ed17ec 65 int BoilerGetPumpSpeedRunOn () { return pumpSpeedRunOn; }
andrewboyson 105:1899f7ed17ec 66 int BoilerGetOutputTarget () { return boilerTarget; }
andrewboyson 105:1899f7ed17ec 67 int BoilerGetMinimumFlow () { return rise16thsAt0; }
andrewboyson 105:1899f7ed17ec 68 int BoilerGetMidFlowSpeed () { return rise16thsAt50; }
andrewboyson 105:1899f7ed17ec 69 int BoilerGetFullSpeedDeltaT () { return rise16thsAt100; }
andrewboyson 0:3c04f4b47041 70
andrewboyson 91:8b192efd0288 71 static void setTankRom (char* value) { memcpy(tankRom, value, 8); FramWrite(iTankRom, 8, tankRom ); }
andrewboyson 91:8b192efd0288 72 static void setOutputRom (char* value) { memcpy(outputRom, value, 8); FramWrite(iOutputRom, 8, outputRom ); }
andrewboyson 91:8b192efd0288 73 static void setReturnRom (char* value) { memcpy(returnRom, value, 8); FramWrite(iReturnRom, 8, returnRom ); }
andrewboyson 105:1899f7ed17ec 74 void BoilerSetFullSpeedSecs (int value) { fullSpeedSecs = value; FramWrite(iFullSpeedSecs, 1, &fullSpeedSecs ); }
andrewboyson 105:1899f7ed17ec 75 void BoilerSetTankSetPoint (int value) { tankSetPoint = value; FramWrite(iTankSetPoint, 1, &tankSetPoint ); }
andrewboyson 104:46ce1aaf8be7 76 void BoilerSetTankHysteresis (int value) { tankHysteresis = value; FramWrite(iTankHysteresis, 2, &tankHysteresis ); }
andrewboyson 105:1899f7ed17ec 77 void BoilerSetRunOnDeltaT (int value) { runOnResidual16ths = value; FramWrite(iRunOnResidual, 2, &runOnResidual16ths ); }
andrewboyson 104:46ce1aaf8be7 78 void BoilerSetRunOnTime (int value) { runOnTime2s = value >> 1;FramWrite(iRunOnTime, 1, &runOnTime2s ); }
andrewboyson 104:46ce1aaf8be7 79 void BoilerSetPumpSpeedCalling (int value) { pumpSpeedCalling = value; FramWrite(iPumpSpeedCalling,1, &pumpSpeedCalling ); }
andrewboyson 104:46ce1aaf8be7 80 void BoilerSetPumpSpeedRunOn (int value) { pumpSpeedRunOn = value; FramWrite(iPumpSpeedRunOn, 1, &pumpSpeedRunOn ); }
andrewboyson 104:46ce1aaf8be7 81 void BoilerSetOutputTarget (int value) { boilerTarget = value; FramWrite(iBoilerTarget, 1, &boilerTarget ); }
andrewboyson 105:1899f7ed17ec 82 void BoilerSetMinimumFlow (int value) { rise16thsAt0 = value; FramWrite(iRiseAt0, 2, &rise16thsAt0 ); }
andrewboyson 105:1899f7ed17ec 83 void BoilerSetMidFlowSpeed (int value) { rise16thsAt50 = value; FramWrite(iRiseAt50, 2, &rise16thsAt50 ); }
andrewboyson 105:1899f7ed17ec 84 void BoilerSetFullSpeedDeltaT (int value) { rise16thsAt100 = value; FramWrite(iRiseAt100, 2, &rise16thsAt100 ); }
andrewboyson 104:46ce1aaf8be7 85
andrewboyson 104:46ce1aaf8be7 86 static int calculateBetweenTwoPoints(int x, int xA, int xB, int yA, int yB)
andrewboyson 104:46ce1aaf8be7 87 {
andrewboyson 104:46ce1aaf8be7 88 float m = (float)(yB - yA) / (xB - xA);
andrewboyson 104:46ce1aaf8be7 89 return yA + m * (x - xA);
andrewboyson 104:46ce1aaf8be7 90 }
andrewboyson 105:1899f7ed17ec 91 static int calculateSpeedFromDeltaT(int deltaT16ths)
andrewboyson 104:46ce1aaf8be7 92 {
andrewboyson 105:1899f7ed17ec 93 if (deltaT16ths < rise16thsAt100) return MAX_SPEED; //Needed in case deltaT16ths is negative or zero
andrewboyson 105:1899f7ed17ec 94 int flow = MAX_SPEED * rise16thsAt100 / deltaT16ths; //eg for 20 deg ==> 100 * (10 << 4) / (20 << 4) == 50
andrewboyson 105:1899f7ed17ec 95 if (flow > MAX_SPEED) flow = MAX_SPEED;
andrewboyson 105:1899f7ed17ec 96 if (flow < MIN_SPEED) flow = MIN_SPEED;
andrewboyson 105:1899f7ed17ec 97 return flow;
andrewboyson 105:1899f7ed17ec 98
andrewboyson 105:1899f7ed17ec 99 //if (deltaT16ths > rise16thsAt0 ) return MIN_SPEED;
andrewboyson 105:1899f7ed17ec 100 //else if (deltaT16ths > rise16thsAt50 ) return calculateBetweenTwoPoints(deltaT16ths, rise16thsAt50, rise16thsAt0, MID_SPEED, MIN_SPEED);
andrewboyson 105:1899f7ed17ec 101 //else if (deltaT16ths > rise16thsAt100) return calculateBetweenTwoPoints(deltaT16ths, rise16thsAt100, rise16thsAt50, MAX_SPEED, MID_SPEED);
andrewboyson 105:1899f7ed17ec 102 //else return MAX_SPEED;
andrewboyson 105:1899f7ed17ec 103 }
andrewboyson 105:1899f7ed17ec 104 static int calculateDeltaTFromSpeed(int speed)
andrewboyson 105:1899f7ed17ec 105 {
andrewboyson 105:1899f7ed17ec 106 int deltaT16ths = MAX_SPEED * rise16thsAt100 / speed; //eg for speed = 50 ==> 100 * (10 << 4) / 50 == 20 << 4
andrewboyson 105:1899f7ed17ec 107 //if (speed >= MAX_SPEED) return rise16thsAt100;
andrewboyson 105:1899f7ed17ec 108 //else if (speed > MID_SPEED) return calculateBetweenTwoPoints(speed, MID_SPEED, MAX_SPEED, rise16thsAt50, rise16thsAt100);
andrewboyson 105:1899f7ed17ec 109 //else if (speed > MIN_SPEED) return calculateBetweenTwoPoints(speed, MIN_SPEED, MID_SPEED, rise16thsAt0, rise16thsAt50 );
andrewboyson 105:1899f7ed17ec 110 //else return rise16thsAt0;
andrewboyson 105:1899f7ed17ec 111 return deltaT16ths;
andrewboyson 104:46ce1aaf8be7 112 }
andrewboyson 0:3c04f4b47041 113
andrewboyson 0:3c04f4b47041 114 int BoilerInit()
andrewboyson 0:3c04f4b47041 115 {
andrewboyson 48:6eac12df3ad5 116 tankRom = DS18B20Roms + 8 * DS18B20RomCount;
andrewboyson 48:6eac12df3ad5 117 DS18B20RomSetters[DS18B20RomCount] = setTankRom;
andrewboyson 48:6eac12df3ad5 118 DS18B20RomNames[DS18B20RomCount] = "Tank";
andrewboyson 48:6eac12df3ad5 119 DS18B20RomCount++;
andrewboyson 48:6eac12df3ad5 120
andrewboyson 48:6eac12df3ad5 121 outputRom = DS18B20Roms + 8 * DS18B20RomCount;
andrewboyson 48:6eac12df3ad5 122 DS18B20RomSetters[DS18B20RomCount] = setOutputRom;
andrewboyson 48:6eac12df3ad5 123 DS18B20RomNames[DS18B20RomCount] = "BlrOut";
andrewboyson 48:6eac12df3ad5 124 DS18B20RomCount++;
andrewboyson 48:6eac12df3ad5 125
andrewboyson 48:6eac12df3ad5 126 returnRom = DS18B20Roms + 8 * DS18B20RomCount;
andrewboyson 48:6eac12df3ad5 127 DS18B20RomSetters[DS18B20RomCount] = setReturnRom;
andrewboyson 48:6eac12df3ad5 128 DS18B20RomNames[DS18B20RomCount] = "BlrRtn";
andrewboyson 48:6eac12df3ad5 129 DS18B20RomCount++;
andrewboyson 48:6eac12df3ad5 130
andrewboyson 0:3c04f4b47041 131 int address;
andrewboyson 104:46ce1aaf8be7 132 uint8_t def1;
andrewboyson 104:46ce1aaf8be7 133 int16_t def2;
andrewboyson 0:3c04f4b47041 134 int32_t def4;
andrewboyson 104:46ce1aaf8be7 135 address = FramLoad( 8, tankRom, 0); if (address < 0) return -1; iTankRom = address;
andrewboyson 104:46ce1aaf8be7 136 address = FramLoad( 8, outputRom, 0); if (address < 0) return -1; iOutputRom = address;
andrewboyson 104:46ce1aaf8be7 137 address = FramLoad( 8, returnRom, 0); if (address < 0) return -1; iReturnRom = address;
andrewboyson 105:1899f7ed17ec 138 def1 = 100; address = FramLoad( 1, &fullSpeedSecs, &def1); if (address < 0) return -1; iFullSpeedSecs = address;
andrewboyson 105:1899f7ed17ec 139 def1 = 65; address = FramLoad( 1, &tankSetPoint, &def1); if (address < 0) return -1; iTankSetPoint = address;
andrewboyson 104:46ce1aaf8be7 140 def2 = 5; address = FramLoad( 2, &tankHysteresis, &def2); if (address < 0) return -1; iTankHysteresis = address;
andrewboyson 104:46ce1aaf8be7 141 def2 = 2; address = FramLoad( 2, &runOnResidual16ths, &def2); if (address < 0) return -1; iRunOnResidual = address;
andrewboyson 104:46ce1aaf8be7 142 def1 = 180; address = FramLoad( 1, &runOnTime2s, &def1); if (address < 0) return -1; iRunOnTime = address;
andrewboyson 104:46ce1aaf8be7 143 def1 = 100; address = FramLoad( 1, &pumpSpeedCalling, &def1); if (address < 0) return -1; iPumpSpeedCalling = address;
andrewboyson 104:46ce1aaf8be7 144 def1 = 10; address = FramLoad( 1, &pumpSpeedRunOn, &def1); if (address < 0) return -1; iPumpSpeedRunOn = address;
andrewboyson 104:46ce1aaf8be7 145 def1 = 65; address = FramLoad( 1, &boilerTarget, &def1); if (address < 0) return -1; iBoilerTarget = address;
andrewboyson 104:46ce1aaf8be7 146 def2 = 10<<4; address = FramLoad( 2, &rise16thsAt0, &def2); if (address < 0) return -1; iRiseAt0 = address;
andrewboyson 104:46ce1aaf8be7 147 def2 = 15<<4; address = FramLoad( 2, &rise16thsAt50, &def2); if (address < 0) return -1; iRiseAt50 = address;
andrewboyson 104:46ce1aaf8be7 148 def2 = 20<<4; address = FramLoad( 2, &rise16thsAt100, &def2); if (address < 0) return -1; iRiseAt100 = address;
andrewboyson 0:3c04f4b47041 149
andrewboyson 5:82197a6997fd 150 BOILER_PUMP_DIR = 1; //Set the direction to 1 == output
andrewboyson 5:82197a6997fd 151 BOILER_CALL_DIR = 1; //Set the direction to 1 == output
andrewboyson 48:6eac12df3ad5 152
andrewboyson 104:46ce1aaf8be7 153 PwmInit(400, 100);
andrewboyson 104:46ce1aaf8be7 154
andrewboyson 0:3c04f4b47041 155 return 0;
andrewboyson 0:3c04f4b47041 156 }
andrewboyson 105:1899f7ed17ec 157 bool BoilerCallEnable = true;
andrewboyson 0:3c04f4b47041 158 bool BoilerCall = false;
andrewboyson 35:bb8a6d1c034c 159 static void controlBoilerCall()
andrewboyson 0:3c04f4b47041 160 {
andrewboyson 105:1899f7ed17ec 161 if (BoilerCallEnable)
andrewboyson 0:3c04f4b47041 162 {
andrewboyson 105:1899f7ed17ec 163 int tankTemp16ths = DS18B20ValueFromRom(tankRom);
andrewboyson 105:1899f7ed17ec 164 if (DS18B20IsValidValue(tankTemp16ths)) //Ignore values which are likely to be wrong
andrewboyson 105:1899f7ed17ec 165 {
andrewboyson 105:1899f7ed17ec 166 int tankUpper16ths = tankSetPoint << 4;
andrewboyson 105:1899f7ed17ec 167 int hysteresis16ths = tankHysteresis << 4;
andrewboyson 105:1899f7ed17ec 168 int tankLower16ths = tankUpper16ths - hysteresis16ths;
andrewboyson 105:1899f7ed17ec 169
andrewboyson 105:1899f7ed17ec 170 if (tankTemp16ths >= tankUpper16ths) BoilerCall = false;
andrewboyson 105:1899f7ed17ec 171 if (tankTemp16ths <= tankLower16ths) BoilerCall = true;
andrewboyson 105:1899f7ed17ec 172 }
andrewboyson 105:1899f7ed17ec 173 }
andrewboyson 105:1899f7ed17ec 174 else
andrewboyson 105:1899f7ed17ec 175 {
andrewboyson 105:1899f7ed17ec 176 BoilerCall = false;
andrewboyson 0:3c04f4b47041 177 }
andrewboyson 35:bb8a6d1c034c 178 }
andrewboyson 35:bb8a6d1c034c 179 bool BoilerPump = false;
andrewboyson 35:bb8a6d1c034c 180 static void controlBoilerPump()
andrewboyson 35:bb8a6d1c034c 181 {
andrewboyson 35:bb8a6d1c034c 182 static uint32_t msTimerBoilerPumpRunOn = 0;
andrewboyson 0:3c04f4b47041 183 if (BoilerCall)
andrewboyson 0:3c04f4b47041 184 {
andrewboyson 0:3c04f4b47041 185 BoilerPump = true;
andrewboyson 35:bb8a6d1c034c 186 msTimerBoilerPumpRunOn = MsTimerCount;
andrewboyson 0:3c04f4b47041 187 }
andrewboyson 0:3c04f4b47041 188 else
andrewboyson 0:3c04f4b47041 189 {
andrewboyson 104:46ce1aaf8be7 190 if (MsTimerRelative(msTimerBoilerPumpRunOn, runOnTime2s * 2000)) BoilerPump = false;
andrewboyson 105:1899f7ed17ec 191 if (_boilerDeltaTisValid && _boilerDeltaT16ths < runOnResidual16ths ) BoilerPump = false;
andrewboyson 104:46ce1aaf8be7 192 }
andrewboyson 104:46ce1aaf8be7 193 }
andrewboyson 105:1899f7ed17ec 194 int BoilerPumpFlow = MIN_SPEED;
andrewboyson 105:1899f7ed17ec 195 int BoilerPumpSpeed = MIN_SPEED;
andrewboyson 104:46ce1aaf8be7 196 int BoilerPumpPwm = 0;
andrewboyson 104:46ce1aaf8be7 197 static int _autoSpeed = 0;
andrewboyson 104:46ce1aaf8be7 198 static void calculateAutoSpeed()
andrewboyson 104:46ce1aaf8be7 199 {
andrewboyson 105:1899f7ed17ec 200 if (!DS18B20IsValidValue(_boilerReturn16ths)) return;
andrewboyson 104:46ce1aaf8be7 201
andrewboyson 104:46ce1aaf8be7 202 int target16ths = (int)boilerTarget << 4;
andrewboyson 105:1899f7ed17ec 203 int targetRise16ths = target16ths - _boilerReturn16ths; //eg 65 - eg 45 = 20*16 16ths
andrewboyson 104:46ce1aaf8be7 204
andrewboyson 105:1899f7ed17ec 205 _autoSpeed = calculateSpeedFromDeltaT(targetRise16ths);
andrewboyson 104:46ce1aaf8be7 206 }
andrewboyson 104:46ce1aaf8be7 207 static void controlBoilerPumpSpeed()
andrewboyson 104:46ce1aaf8be7 208 {
andrewboyson 104:46ce1aaf8be7 209 static uint32_t msTimerReduction = 0;
andrewboyson 104:46ce1aaf8be7 210 calculateAutoSpeed();
andrewboyson 104:46ce1aaf8be7 211 if (BoilerCall)
andrewboyson 104:46ce1aaf8be7 212 {
andrewboyson 105:1899f7ed17ec 213 if (pumpSpeedCalling > MAX_SPEED || pumpSpeedCalling < MIN_SPEED) BoilerPumpSpeed = _autoSpeed; //Auto
andrewboyson 105:1899f7ed17ec 214 else BoilerPumpSpeed = pumpSpeedCalling; //Manual
andrewboyson 104:46ce1aaf8be7 215 msTimerReduction = MsTimerCount;
andrewboyson 104:46ce1aaf8be7 216 }
andrewboyson 104:46ce1aaf8be7 217 else
andrewboyson 104:46ce1aaf8be7 218 {
andrewboyson 104:46ce1aaf8be7 219 if (BoilerPumpSpeed > pumpSpeedRunOn)
andrewboyson 104:46ce1aaf8be7 220 {
andrewboyson 104:46ce1aaf8be7 221 if (MsTimerRepetitive(&msTimerReduction, 250)) BoilerPumpSpeed--;
andrewboyson 104:46ce1aaf8be7 222 }
andrewboyson 104:46ce1aaf8be7 223 else
andrewboyson 104:46ce1aaf8be7 224 {
andrewboyson 104:46ce1aaf8be7 225 BoilerPumpSpeed = pumpSpeedRunOn;
andrewboyson 104:46ce1aaf8be7 226 }
andrewboyson 0:3c04f4b47041 227 }
andrewboyson 35:bb8a6d1c034c 228 }
andrewboyson 105:1899f7ed17ec 229 static void flowToSpeed()
andrewboyson 105:1899f7ed17ec 230 {
andrewboyson 105:1899f7ed17ec 231 //Do nothing yet
andrewboyson 105:1899f7ed17ec 232 }
andrewboyson 104:46ce1aaf8be7 233 static void speedToPwm()
andrewboyson 104:46ce1aaf8be7 234 {
andrewboyson 104:46ce1aaf8be7 235 /*
andrewboyson 104:46ce1aaf8be7 236 PWM input signal [%] Pump status
andrewboyson 104:46ce1aaf8be7 237 ≤ 10 Maximum speed
andrewboyson 104:46ce1aaf8be7 238 > 10 / ≤ 84 Variable speed from minimum to maximum
andrewboyson 104:46ce1aaf8be7 239 speed
andrewboyson 104:46ce1aaf8be7 240 > 84 / ≤ 91 Minimum speed
andrewboyson 104:46ce1aaf8be7 241 > 91/95 Hysteresis area: on/off
andrewboyson 104:46ce1aaf8be7 242 > 95 / ≤ 100 Standby mode: off
andrewboyson 104:46ce1aaf8be7 243
andrewboyson 104:46ce1aaf8be7 244 Max speed 100 is at fitted = 74; pwm = 10
andrewboyson 104:46ce1aaf8be7 245 Min speed 0 is at fitted = 0; pwm = 84
andrewboyson 104:46ce1aaf8be7 246 */
andrewboyson 105:1899f7ed17ec 247 int pwm = calculateBetweenTwoPoints(BoilerPumpSpeed, MIN_SPEED, MAX_SPEED, 84, 10);
andrewboyson 105:1899f7ed17ec 248 if (pwm < 10) pwm = 10;
andrewboyson 105:1899f7ed17ec 249 if (pwm > 84) pwm = 84;
andrewboyson 105:1899f7ed17ec 250 BoilerPumpPwm = pwm;
andrewboyson 104:46ce1aaf8be7 251 }
andrewboyson 104:46ce1aaf8be7 252 #define TIME_BEFORE_TWEAK_SECS 120
andrewboyson 104:46ce1aaf8be7 253 static void tweakDeltaTs()
andrewboyson 104:46ce1aaf8be7 254 {
andrewboyson 105:1899f7ed17ec 255 if (pumpSpeedCalling != PUMP_SPEED_CALLING_AUTO_TWEAK) return;
andrewboyson 105:1899f7ed17ec 256
andrewboyson 104:46ce1aaf8be7 257 static uint32_t msTimerBoilerHeating = 0;
andrewboyson 104:46ce1aaf8be7 258 if (!BoilerCall) msTimerBoilerHeating = MsTimerCount;
andrewboyson 104:46ce1aaf8be7 259 if (!MsTimerRelative(msTimerBoilerHeating, TIME_BEFORE_TWEAK_SECS * 1000)) return;
andrewboyson 104:46ce1aaf8be7 260
andrewboyson 105:1899f7ed17ec 261 if (!_boilerDeltaTisValid) return;
andrewboyson 104:46ce1aaf8be7 262
andrewboyson 104:46ce1aaf8be7 263 static int speedLastScan = -1;
andrewboyson 104:46ce1aaf8be7 264
andrewboyson 105:1899f7ed17ec 265 if (speedLastScan < MAX_SPEED && BoilerPumpSpeed == MAX_SPEED)
andrewboyson 104:46ce1aaf8be7 266 {
andrewboyson 105:1899f7ed17ec 267 if (rise16thsAt100 > _boilerDeltaT16ths) rise16thsAt100--;
andrewboyson 105:1899f7ed17ec 268 if (rise16thsAt100 < _boilerDeltaT16ths) rise16thsAt100++;
andrewboyson 104:46ce1aaf8be7 269 }
andrewboyson 104:46ce1aaf8be7 270
andrewboyson 104:46ce1aaf8be7 271 speedLastScan = BoilerPumpSpeed;
andrewboyson 104:46ce1aaf8be7 272 }
andrewboyson 105:1899f7ed17ec 273
andrewboyson 105:1899f7ed17ec 274 #define TIME_BEFORE_DELTA_T_ALARM_SECS 300
andrewboyson 105:1899f7ed17ec 275 #define DELTA_T_LIMIT (3 << 4)
andrewboyson 105:1899f7ed17ec 276 static void checkDeltaTs()
andrewboyson 105:1899f7ed17ec 277 {
andrewboyson 105:1899f7ed17ec 278 static uint32_t msTimerDeltaTNonConform = 0;
andrewboyson 105:1899f7ed17ec 279 if (!BoilerCall)
andrewboyson 105:1899f7ed17ec 280 {
andrewboyson 105:1899f7ed17ec 281 msTimerDeltaTNonConform = MsTimerCount;
andrewboyson 105:1899f7ed17ec 282 return;
andrewboyson 105:1899f7ed17ec 283 }
andrewboyson 105:1899f7ed17ec 284
andrewboyson 105:1899f7ed17ec 285 int expectedDeltaT16ths = calculateDeltaTFromSpeed(BoilerPumpSpeed);
andrewboyson 105:1899f7ed17ec 286
andrewboyson 105:1899f7ed17ec 287 bool deltaTisOk = _boilerDeltaTisValid &&
andrewboyson 105:1899f7ed17ec 288 _boilerDeltaT16ths > (expectedDeltaT16ths - DELTA_T_LIMIT) &&
andrewboyson 105:1899f7ed17ec 289 _boilerDeltaT16ths < (expectedDeltaT16ths + DELTA_T_LIMIT);
andrewboyson 105:1899f7ed17ec 290
andrewboyson 105:1899f7ed17ec 291
andrewboyson 105:1899f7ed17ec 292 static bool deltaTwasOk = true;
andrewboyson 105:1899f7ed17ec 293
andrewboyson 105:1899f7ed17ec 294 /*
andrewboyson 105:1899f7ed17ec 295 if (deltaTwasOk != deltaTisOk)
andrewboyson 105:1899f7ed17ec 296 {
andrewboyson 105:1899f7ed17ec 297 LogTimeF("Boiler delta T ");
andrewboyson 105:1899f7ed17ec 298 DS18B20Log(_boilerDeltaT16ths);
andrewboyson 105:1899f7ed17ec 299 if (deltaTisOk)
andrewboyson 105:1899f7ed17ec 300 {
andrewboyson 105:1899f7ed17ec 301 Log(" is inside expected value ");
andrewboyson 105:1899f7ed17ec 302 }
andrewboyson 105:1899f7ed17ec 303 else
andrewboyson 105:1899f7ed17ec 304 {
andrewboyson 105:1899f7ed17ec 305 Log(" is outside expected value ");
andrewboyson 105:1899f7ed17ec 306 }
andrewboyson 105:1899f7ed17ec 307 DS18B20Log(expectedDeltaT16ths);
andrewboyson 105:1899f7ed17ec 308 Log("\r\n");
andrewboyson 105:1899f7ed17ec 309 }
andrewboyson 105:1899f7ed17ec 310
andrewboyson 105:1899f7ed17ec 311 deltaTwasOk = deltaTisOk;
andrewboyson 105:1899f7ed17ec 312 */
andrewboyson 105:1899f7ed17ec 313
andrewboyson 105:1899f7ed17ec 314 static bool hadAlarm = false;
andrewboyson 105:1899f7ed17ec 315 if (deltaTisOk) msTimerDeltaTNonConform = MsTimerCount;
andrewboyson 105:1899f7ed17ec 316 bool haveAlarm = MsTimerRelative(msTimerDeltaTNonConform, TIME_BEFORE_DELTA_T_ALARM_SECS * 1000);
andrewboyson 105:1899f7ed17ec 317 if (haveAlarm && !hadAlarm)
andrewboyson 105:1899f7ed17ec 318 {
andrewboyson 105:1899f7ed17ec 319 LogTimeF("Boiler delta T would have tripped after not being ok for %d seconds\r\n", TIME_BEFORE_DELTA_T_ALARM_SECS);
andrewboyson 105:1899f7ed17ec 320 }
andrewboyson 105:1899f7ed17ec 321 hadAlarm = haveAlarm;
andrewboyson 105:1899f7ed17ec 322 }
andrewboyson 105:1899f7ed17ec 323 #define NUMBER_OF_STEPS 10
andrewboyson 105:1899f7ed17ec 324 static int16_t _returns16ths[NUMBER_OF_STEPS]; //0 is last, 9th is first
andrewboyson 105:1899f7ed17ec 325 static void delayLine()
andrewboyson 105:1899f7ed17ec 326 {
andrewboyson 105:1899f7ed17ec 327 static uint32_t msTimerDelay = 0;
andrewboyson 105:1899f7ed17ec 328 if (BoilerPump)
andrewboyson 105:1899f7ed17ec 329 {
andrewboyson 105:1899f7ed17ec 330 int msTotal = 1000 * fullSpeedSecs * MAX_SPEED / BoilerPumpSpeed; //speed 10 ==> 10000; speed 100 ==> 1000
andrewboyson 105:1899f7ed17ec 331 int msPerStep = msTotal / NUMBER_OF_STEPS;
andrewboyson 105:1899f7ed17ec 332 if (MsTimerRelative(msTimerDelay, msPerStep))
andrewboyson 105:1899f7ed17ec 333 {
andrewboyson 105:1899f7ed17ec 334 for (int i = 0; i < NUMBER_OF_STEPS - 1; i++) _returns16ths[i] = _returns16ths[i + 1];
andrewboyson 105:1899f7ed17ec 335 _returns16ths[NUMBER_OF_STEPS - 1] = _boilerReturn16ths;
andrewboyson 105:1899f7ed17ec 336 msTimerDelay = MsTimerCount;
andrewboyson 105:1899f7ed17ec 337 //LogTimeF("Ms per step = %d, delayed boiler return = ", msPerStep);
andrewboyson 105:1899f7ed17ec 338 //DS18B20Log(_returns16ths[0]);
andrewboyson 105:1899f7ed17ec 339 //Log("\r\n");
andrewboyson 105:1899f7ed17ec 340 }
andrewboyson 105:1899f7ed17ec 341 }
andrewboyson 105:1899f7ed17ec 342 else
andrewboyson 105:1899f7ed17ec 343 {
andrewboyson 105:1899f7ed17ec 344 msTimerDelay = MsTimerCount;
andrewboyson 105:1899f7ed17ec 345 for (int i = 0; i < NUMBER_OF_STEPS; i++) _returns16ths[i] = DS18B20_ERROR_VALUE_NOT_SET;
andrewboyson 105:1899f7ed17ec 346 }
andrewboyson 105:1899f7ed17ec 347 }
andrewboyson 105:1899f7ed17ec 348
andrewboyson 35:bb8a6d1c034c 349 void BoilerMain()
andrewboyson 35:bb8a6d1c034c 350 {
andrewboyson 105:1899f7ed17ec 351 delayLine();
andrewboyson 105:1899f7ed17ec 352 _boilerOutput16ths = DS18B20ValueFromRom(outputRom);
andrewboyson 105:1899f7ed17ec 353 _boilerReturn16ths = DS18B20ValueFromRom(returnRom);
andrewboyson 105:1899f7ed17ec 354 _boilerRtnDel16ths = _returns16ths[0];
andrewboyson 105:1899f7ed17ec 355 _boilerDeltaTisValid = DS18B20IsValidValue(_boilerOutput16ths) && DS18B20IsValidValue(_boilerRtnDel16ths);
andrewboyson 105:1899f7ed17ec 356 if (_boilerDeltaTisValid) _boilerDeltaT16ths = _boilerOutput16ths - _boilerRtnDel16ths;
andrewboyson 105:1899f7ed17ec 357 else _boilerDeltaT16ths = DS18B20_ERROR_VALUE_NOT_SET;
andrewboyson 105:1899f7ed17ec 358
andrewboyson 35:bb8a6d1c034c 359 controlBoilerCall();
andrewboyson 35:bb8a6d1c034c 360 if (BoilerCall) BOILER_CALL_SET;
andrewboyson 35:bb8a6d1c034c 361 else BOILER_CALL_CLR;
andrewboyson 0:3c04f4b47041 362
andrewboyson 35:bb8a6d1c034c 363 controlBoilerPump();
andrewboyson 5:82197a6997fd 364 if (BoilerPump) BOILER_PUMP_SET;
andrewboyson 5:82197a6997fd 365 else BOILER_PUMP_CLR;
andrewboyson 0:3c04f4b47041 366
andrewboyson 104:46ce1aaf8be7 367 controlBoilerPumpSpeed();
andrewboyson 105:1899f7ed17ec 368 flowToSpeed();
andrewboyson 104:46ce1aaf8be7 369 speedToPwm();
andrewboyson 104:46ce1aaf8be7 370 PwmSet(BoilerPumpPwm);
andrewboyson 104:46ce1aaf8be7 371
andrewboyson 104:46ce1aaf8be7 372 tweakDeltaTs();
andrewboyson 105:1899f7ed17ec 373 checkDeltaTs();
andrewboyson 0:3c04f4b47041 374 }