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:
Wed Feb 10 17:24:36 2021 +0000
Revision:
104:46ce1aaf8be7
Parent:
91:8b192efd0288
Child:
105:1899f7ed17ec
Added PWM speed control to the boiler pump.

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 48:6eac12df3ad5 22 static char* tankRom; static int iTankRom;
andrewboyson 48:6eac12df3ad5 23 static char* outputRom; static int iOutputRom;
andrewboyson 48:6eac12df3ad5 24 static char* returnRom; static int iReturnRom;
andrewboyson 0:3c04f4b47041 25
andrewboyson 104:46ce1aaf8be7 26 static int16_t tankSetPoint; static int iTankSetPoint;
andrewboyson 104:46ce1aaf8be7 27 static int16_t tankHysteresis; static int iTankHysteresis;
andrewboyson 104:46ce1aaf8be7 28 static int16_t runOnResidual16ths; static int iRunOnResidual;
andrewboyson 104:46ce1aaf8be7 29 static uint8_t runOnTime2s; static int iRunOnTime;
andrewboyson 104:46ce1aaf8be7 30
andrewboyson 104:46ce1aaf8be7 31 static int8_t boilerTarget; static int iBoilerTarget;
andrewboyson 104:46ce1aaf8be7 32 static int8_t pumpSpeedCalling; static int iPumpSpeedCalling;
andrewboyson 104:46ce1aaf8be7 33 static int8_t pumpSpeedRunOn; static int iPumpSpeedRunOn;
andrewboyson 104:46ce1aaf8be7 34
andrewboyson 104:46ce1aaf8be7 35 static int16_t rise16thsAt0; static int iRiseAt0;
andrewboyson 104:46ce1aaf8be7 36 static int16_t rise16thsAt50; static int iRiseAt50;
andrewboyson 104:46ce1aaf8be7 37 static int16_t rise16thsAt100; static int iRiseAt100;
andrewboyson 0:3c04f4b47041 38
andrewboyson 48:6eac12df3ad5 39 uint16_t BoilerGetTankDS18B20Value () { return DS18B20ValueFromRom(tankRom); }
andrewboyson 48:6eac12df3ad5 40 uint16_t BoilerGetOutputDS18B20Value() { return DS18B20ValueFromRom(outputRom); }
andrewboyson 48:6eac12df3ad5 41 uint16_t BoilerGetReturnDS18B20Value() { return DS18B20ValueFromRom(returnRom); }
andrewboyson 104:46ce1aaf8be7 42 int BoilerGetTankSetPoint () { return tankSetPoint; }
andrewboyson 104:46ce1aaf8be7 43 int BoilerGetTankHysteresis () { return tankHysteresis; }
andrewboyson 104:46ce1aaf8be7 44 int BoilerGetRunOnResidual16ths() { return runOnResidual16ths;}
andrewboyson 104:46ce1aaf8be7 45 int BoilerGetRunOnTime () { return runOnTime2s << 1; }
andrewboyson 104:46ce1aaf8be7 46 int BoilerGetPumpSpeedCalling () { return pumpSpeedCalling; }
andrewboyson 104:46ce1aaf8be7 47 int BoilerGetPumpSpeedRunOn () { return pumpSpeedRunOn; }
andrewboyson 104:46ce1aaf8be7 48 int BoilerGetOutputTarget () { return boilerTarget; }
andrewboyson 104:46ce1aaf8be7 49 int BoilerGetRise16thsAt0 () { return rise16thsAt0; }
andrewboyson 104:46ce1aaf8be7 50 int BoilerGetRise16thsAt50 () { return rise16thsAt50; }
andrewboyson 104:46ce1aaf8be7 51 int BoilerGetRise16thsAt100 () { return rise16thsAt100; }
andrewboyson 0:3c04f4b47041 52
andrewboyson 91:8b192efd0288 53 static void setTankRom (char* value) { memcpy(tankRom, value, 8); FramWrite(iTankRom, 8, tankRom ); }
andrewboyson 91:8b192efd0288 54 static void setOutputRom (char* value) { memcpy(outputRom, value, 8); FramWrite(iOutputRom, 8, outputRom ); }
andrewboyson 91:8b192efd0288 55 static void setReturnRom (char* value) { memcpy(returnRom, value, 8); FramWrite(iReturnRom, 8, returnRom ); }
andrewboyson 104:46ce1aaf8be7 56 void BoilerSetTankSetPoint (int value) { tankSetPoint = value; FramWrite(iTankSetPoint, 2, &tankSetPoint ); }
andrewboyson 104:46ce1aaf8be7 57 void BoilerSetTankHysteresis (int value) { tankHysteresis = value; FramWrite(iTankHysteresis, 2, &tankHysteresis ); }
andrewboyson 104:46ce1aaf8be7 58 void BoilerSetRunOnResidual16ths(int value) { runOnResidual16ths = value; FramWrite(iRunOnResidual, 2, &runOnResidual16ths ); }
andrewboyson 104:46ce1aaf8be7 59 void BoilerSetRunOnTime (int value) { runOnTime2s = value >> 1;FramWrite(iRunOnTime, 1, &runOnTime2s ); }
andrewboyson 104:46ce1aaf8be7 60 void BoilerSetPumpSpeedCalling (int value) { pumpSpeedCalling = value; FramWrite(iPumpSpeedCalling,1, &pumpSpeedCalling ); }
andrewboyson 104:46ce1aaf8be7 61 void BoilerSetPumpSpeedRunOn (int value) { pumpSpeedRunOn = value; FramWrite(iPumpSpeedRunOn, 1, &pumpSpeedRunOn ); }
andrewboyson 104:46ce1aaf8be7 62 void BoilerSetOutputTarget (int value) { boilerTarget = value; FramWrite(iBoilerTarget, 1, &boilerTarget ); }
andrewboyson 104:46ce1aaf8be7 63 void BoilerSetRise16thsAt0 (int value) { rise16thsAt0 = value; FramWrite(iRiseAt0, 2, &rise16thsAt0 ); }
andrewboyson 104:46ce1aaf8be7 64 void BoilerSetRise16thsAt50 (int value) { rise16thsAt50 = value; FramWrite(iRiseAt50, 2, &rise16thsAt50 ); }
andrewboyson 104:46ce1aaf8be7 65 void BoilerSetRise16thsAt100 (int value) { rise16thsAt100 = value; FramWrite(iRiseAt100, 2, &rise16thsAt100 ); }
andrewboyson 104:46ce1aaf8be7 66
andrewboyson 104:46ce1aaf8be7 67 static int calculateBetweenTwoPoints(int x, int xA, int xB, int yA, int yB)
andrewboyson 104:46ce1aaf8be7 68 {
andrewboyson 104:46ce1aaf8be7 69 float m = (float)(yB - yA) / (xB - xA);
andrewboyson 104:46ce1aaf8be7 70 return yA + m * (x - xA);
andrewboyson 104:46ce1aaf8be7 71 }
andrewboyson 104:46ce1aaf8be7 72 static int oldcalculateBetweenTwoPoints(int point16ths, int pointBig16ths, int pointSmall16ths, int bigSpeed, int width) //width = 1 for 100; 2 for 50 and 4 for 25
andrewboyson 104:46ce1aaf8be7 73 {
andrewboyson 104:46ce1aaf8be7 74 //Expected to have to compensate the slope for the reduced width but didn't need to.
andrewboyson 104:46ce1aaf8be7 75 int slope = pointBig16ths - pointSmall16ths;
andrewboyson 104:46ce1aaf8be7 76 int diff16ths = point16ths - pointSmall16ths;
andrewboyson 104:46ce1aaf8be7 77 int diffSpeed = (diff16ths * slope * width) >> 8; //points are in 16ths so multiplying them needs a division by 256
andrewboyson 104:46ce1aaf8be7 78 int requiredSpeed = bigSpeed - diffSpeed;
andrewboyson 104:46ce1aaf8be7 79 if (requiredSpeed > 100) requiredSpeed = 100;
andrewboyson 104:46ce1aaf8be7 80 if (requiredSpeed < 0) requiredSpeed = 0;
andrewboyson 104:46ce1aaf8be7 81 return requiredSpeed;
andrewboyson 104:46ce1aaf8be7 82 }
andrewboyson 104:46ce1aaf8be7 83
andrewboyson 104:46ce1aaf8be7 84 static int calculatePoint(int targetRise16ths)
andrewboyson 104:46ce1aaf8be7 85 {
andrewboyson 104:46ce1aaf8be7 86 if (targetRise16ths > rise16thsAt0) //20
andrewboyson 104:46ce1aaf8be7 87 {
andrewboyson 104:46ce1aaf8be7 88 return 0;
andrewboyson 104:46ce1aaf8be7 89 }
andrewboyson 104:46ce1aaf8be7 90 else if (targetRise16ths > rise16thsAt50) //15
andrewboyson 104:46ce1aaf8be7 91 {
andrewboyson 104:46ce1aaf8be7 92 return calculateBetweenTwoPoints(targetRise16ths, rise16thsAt50, rise16thsAt0, 50, 0);
andrewboyson 104:46ce1aaf8be7 93 //return oldcalculateBetweenTwoPoints(targetRise16ths, rise16thsAt0, rise16thsAt50, 50, 2);
andrewboyson 104:46ce1aaf8be7 94 }
andrewboyson 104:46ce1aaf8be7 95 else if (targetRise16ths > rise16thsAt100) //10
andrewboyson 104:46ce1aaf8be7 96 {
andrewboyson 104:46ce1aaf8be7 97 return calculateBetweenTwoPoints(targetRise16ths, rise16thsAt100, rise16thsAt50, 100, 50);
andrewboyson 104:46ce1aaf8be7 98 //return oldcalculateBetweenTwoPoints(targetRise16ths, rise16thsAt50, rise16thsAt100, 100, 2);
andrewboyson 104:46ce1aaf8be7 99 }
andrewboyson 104:46ce1aaf8be7 100 else
andrewboyson 104:46ce1aaf8be7 101 {
andrewboyson 104:46ce1aaf8be7 102 return 100;
andrewboyson 104:46ce1aaf8be7 103 }
andrewboyson 104:46ce1aaf8be7 104 }
andrewboyson 0:3c04f4b47041 105
andrewboyson 0:3c04f4b47041 106 int BoilerInit()
andrewboyson 0:3c04f4b47041 107 {
andrewboyson 48:6eac12df3ad5 108 tankRom = DS18B20Roms + 8 * DS18B20RomCount;
andrewboyson 48:6eac12df3ad5 109 DS18B20RomSetters[DS18B20RomCount] = setTankRom;
andrewboyson 48:6eac12df3ad5 110 DS18B20RomNames[DS18B20RomCount] = "Tank";
andrewboyson 48:6eac12df3ad5 111 DS18B20RomCount++;
andrewboyson 48:6eac12df3ad5 112
andrewboyson 48:6eac12df3ad5 113 outputRom = DS18B20Roms + 8 * DS18B20RomCount;
andrewboyson 48:6eac12df3ad5 114 DS18B20RomSetters[DS18B20RomCount] = setOutputRom;
andrewboyson 48:6eac12df3ad5 115 DS18B20RomNames[DS18B20RomCount] = "BlrOut";
andrewboyson 48:6eac12df3ad5 116 DS18B20RomCount++;
andrewboyson 48:6eac12df3ad5 117
andrewboyson 48:6eac12df3ad5 118 returnRom = DS18B20Roms + 8 * DS18B20RomCount;
andrewboyson 48:6eac12df3ad5 119 DS18B20RomSetters[DS18B20RomCount] = setReturnRom;
andrewboyson 48:6eac12df3ad5 120 DS18B20RomNames[DS18B20RomCount] = "BlrRtn";
andrewboyson 48:6eac12df3ad5 121 DS18B20RomCount++;
andrewboyson 48:6eac12df3ad5 122
andrewboyson 0:3c04f4b47041 123 int address;
andrewboyson 104:46ce1aaf8be7 124 uint8_t def1;
andrewboyson 104:46ce1aaf8be7 125 int16_t def2;
andrewboyson 0:3c04f4b47041 126 int32_t def4;
andrewboyson 104:46ce1aaf8be7 127 address = FramLoad( 8, tankRom, 0); if (address < 0) return -1; iTankRom = address;
andrewboyson 104:46ce1aaf8be7 128 address = FramLoad( 8, outputRom, 0); if (address < 0) return -1; iOutputRom = address;
andrewboyson 104:46ce1aaf8be7 129 address = FramLoad( 8, returnRom, 0); if (address < 0) return -1; iReturnRom = address;
andrewboyson 104:46ce1aaf8be7 130 def2 = 65; address = FramLoad( 2, &tankSetPoint, &def2); if (address < 0) return -1; iTankSetPoint = address;
andrewboyson 104:46ce1aaf8be7 131 def2 = 5; address = FramLoad( 2, &tankHysteresis, &def2); if (address < 0) return -1; iTankHysteresis = address;
andrewboyson 104:46ce1aaf8be7 132 def2 = 2; address = FramLoad( 2, &runOnResidual16ths, &def2); if (address < 0) return -1; iRunOnResidual = address;
andrewboyson 104:46ce1aaf8be7 133 def1 = 180; address = FramLoad( 1, &runOnTime2s, &def1); if (address < 0) return -1; iRunOnTime = address;
andrewboyson 104:46ce1aaf8be7 134 def1 = 100; address = FramLoad( 1, &pumpSpeedCalling, &def1); if (address < 0) return -1; iPumpSpeedCalling = address;
andrewboyson 104:46ce1aaf8be7 135 def1 = 10; address = FramLoad( 1, &pumpSpeedRunOn, &def1); if (address < 0) return -1; iPumpSpeedRunOn = address;
andrewboyson 104:46ce1aaf8be7 136 def1 = 65; address = FramLoad( 1, &boilerTarget, &def1); if (address < 0) return -1; iBoilerTarget = address;
andrewboyson 104:46ce1aaf8be7 137 def2 = 10<<4; address = FramLoad( 2, &rise16thsAt0, &def2); if (address < 0) return -1; iRiseAt0 = address;
andrewboyson 104:46ce1aaf8be7 138 def2 = 15<<4; address = FramLoad( 2, &rise16thsAt50, &def2); if (address < 0) return -1; iRiseAt50 = address;
andrewboyson 104:46ce1aaf8be7 139 def2 = 20<<4; address = FramLoad( 2, &rise16thsAt100, &def2); if (address < 0) return -1; iRiseAt100 = address;
andrewboyson 0:3c04f4b47041 140
andrewboyson 5:82197a6997fd 141 BOILER_PUMP_DIR = 1; //Set the direction to 1 == output
andrewboyson 5:82197a6997fd 142 BOILER_CALL_DIR = 1; //Set the direction to 1 == output
andrewboyson 48:6eac12df3ad5 143
andrewboyson 104:46ce1aaf8be7 144 PwmInit(400, 100);
andrewboyson 104:46ce1aaf8be7 145
andrewboyson 104:46ce1aaf8be7 146 for (int deltaT = 30; deltaT > 0; deltaT--)
andrewboyson 104:46ce1aaf8be7 147 {
andrewboyson 104:46ce1aaf8be7 148 LogF("DeltaT %d ==> speed %d\r\n", deltaT, calculatePoint(deltaT << 4));
andrewboyson 104:46ce1aaf8be7 149 }
andrewboyson 104:46ce1aaf8be7 150
andrewboyson 0:3c04f4b47041 151 return 0;
andrewboyson 0:3c04f4b47041 152 }
andrewboyson 0:3c04f4b47041 153 bool BoilerCall = false;
andrewboyson 35:bb8a6d1c034c 154 static void controlBoilerCall()
andrewboyson 0:3c04f4b47041 155 {
andrewboyson 0:3c04f4b47041 156 int tankTemp16ths = DS18B20ValueFromRom(tankRom);
andrewboyson 0:3c04f4b47041 157 if (DS18B20IsValidValue(tankTemp16ths)) //Ignore values which are likely to be wrong
andrewboyson 0:3c04f4b47041 158 {
andrewboyson 0:3c04f4b47041 159 int tankUpper16ths = tankSetPoint << 4;
andrewboyson 0:3c04f4b47041 160 int hysteresis16ths = tankHysteresis << 4;
andrewboyson 0:3c04f4b47041 161 int tankLower16ths = tankUpper16ths - hysteresis16ths;
andrewboyson 0:3c04f4b47041 162
andrewboyson 0:3c04f4b47041 163 if (tankTemp16ths >= tankUpper16ths) BoilerCall = false;
andrewboyson 0:3c04f4b47041 164 if (tankTemp16ths <= tankLower16ths) BoilerCall = true;
andrewboyson 0:3c04f4b47041 165 }
andrewboyson 35:bb8a6d1c034c 166 }
andrewboyson 35:bb8a6d1c034c 167 bool BoilerPump = false;
andrewboyson 35:bb8a6d1c034c 168 static void controlBoilerPump()
andrewboyson 35:bb8a6d1c034c 169 {
andrewboyson 104:46ce1aaf8be7 170 int16_t boilerOutput16ths = DS18B20ValueFromRom(outputRom);
andrewboyson 104:46ce1aaf8be7 171 int16_t boilerReturn16ths = DS18B20ValueFromRom(returnRom);
andrewboyson 104:46ce1aaf8be7 172 int16_t boilerResidual16ths = boilerOutput16ths - boilerReturn16ths;
andrewboyson 104:46ce1aaf8be7 173 bool boilerTempsAreValid = DS18B20IsValidValue(boilerOutput16ths) && DS18B20IsValidValue(boilerReturn16ths);
andrewboyson 0:3c04f4b47041 174
andrewboyson 35:bb8a6d1c034c 175 static uint32_t msTimerBoilerPumpRunOn = 0;
andrewboyson 0:3c04f4b47041 176 if (BoilerCall)
andrewboyson 0:3c04f4b47041 177 {
andrewboyson 0:3c04f4b47041 178 BoilerPump = true;
andrewboyson 35:bb8a6d1c034c 179 msTimerBoilerPumpRunOn = MsTimerCount;
andrewboyson 0:3c04f4b47041 180 }
andrewboyson 0:3c04f4b47041 181 else
andrewboyson 0:3c04f4b47041 182 {
andrewboyson 104:46ce1aaf8be7 183 if (MsTimerRelative(msTimerBoilerPumpRunOn, runOnTime2s * 2000)) BoilerPump = false;
andrewboyson 104:46ce1aaf8be7 184 if (boilerTempsAreValid && boilerResidual16ths < runOnResidual16ths ) BoilerPump = false;
andrewboyson 104:46ce1aaf8be7 185 }
andrewboyson 104:46ce1aaf8be7 186 }
andrewboyson 104:46ce1aaf8be7 187 int BoilerPumpSpeed = 0;
andrewboyson 104:46ce1aaf8be7 188 int BoilerPumpPwm = 0;
andrewboyson 104:46ce1aaf8be7 189 static int _autoSpeed = 0;
andrewboyson 104:46ce1aaf8be7 190 static void calculateAutoSpeed()
andrewboyson 104:46ce1aaf8be7 191 {
andrewboyson 104:46ce1aaf8be7 192 int16_t boilerOutput16ths = DS18B20ValueFromRom(outputRom);
andrewboyson 104:46ce1aaf8be7 193 int16_t boilerReturn16ths = DS18B20ValueFromRom(returnRom);
andrewboyson 104:46ce1aaf8be7 194 int16_t boilerResidual16ths = boilerOutput16ths - boilerReturn16ths;
andrewboyson 104:46ce1aaf8be7 195 bool boilerTempsAreValid = DS18B20IsValidValue(boilerOutput16ths) && DS18B20IsValidValue(boilerReturn16ths);
andrewboyson 104:46ce1aaf8be7 196
andrewboyson 104:46ce1aaf8be7 197 if (!boilerTempsAreValid) return;
andrewboyson 104:46ce1aaf8be7 198
andrewboyson 104:46ce1aaf8be7 199 int target16ths = (int)boilerTarget << 4;
andrewboyson 104:46ce1aaf8be7 200 int targetRise16ths = target16ths - boilerReturn16ths; //eg 65 - eg 45 = 20*16 16ths
andrewboyson 104:46ce1aaf8be7 201
andrewboyson 104:46ce1aaf8be7 202 _autoSpeed = calculatePoint(targetRise16ths);
andrewboyson 104:46ce1aaf8be7 203 }
andrewboyson 104:46ce1aaf8be7 204 static void controlBoilerPumpSpeed()
andrewboyson 104:46ce1aaf8be7 205 {
andrewboyson 104:46ce1aaf8be7 206 static uint32_t msTimerReduction = 0;
andrewboyson 104:46ce1aaf8be7 207 calculateAutoSpeed();
andrewboyson 104:46ce1aaf8be7 208 if (BoilerCall)
andrewboyson 104:46ce1aaf8be7 209 {
andrewboyson 104:46ce1aaf8be7 210 if (pumpSpeedCalling > 100 || pumpSpeedCalling < 0) BoilerPumpSpeed = _autoSpeed; //Auto
andrewboyson 104:46ce1aaf8be7 211 else BoilerPumpSpeed = pumpSpeedCalling; //Manual
andrewboyson 104:46ce1aaf8be7 212 msTimerReduction = MsTimerCount;
andrewboyson 104:46ce1aaf8be7 213 }
andrewboyson 104:46ce1aaf8be7 214 else
andrewboyson 104:46ce1aaf8be7 215 {
andrewboyson 104:46ce1aaf8be7 216 if (BoilerPumpSpeed > pumpSpeedRunOn)
andrewboyson 104:46ce1aaf8be7 217 {
andrewboyson 104:46ce1aaf8be7 218 if (MsTimerRepetitive(&msTimerReduction, 250)) BoilerPumpSpeed--;
andrewboyson 104:46ce1aaf8be7 219 }
andrewboyson 104:46ce1aaf8be7 220 else
andrewboyson 104:46ce1aaf8be7 221 {
andrewboyson 104:46ce1aaf8be7 222 BoilerPumpSpeed = pumpSpeedRunOn;
andrewboyson 104:46ce1aaf8be7 223 }
andrewboyson 0:3c04f4b47041 224 }
andrewboyson 35:bb8a6d1c034c 225 }
andrewboyson 104:46ce1aaf8be7 226 static void speedToPwm()
andrewboyson 104:46ce1aaf8be7 227 {
andrewboyson 104:46ce1aaf8be7 228 /*
andrewboyson 104:46ce1aaf8be7 229 PWM input signal [%] Pump status
andrewboyson 104:46ce1aaf8be7 230 ≤ 10 Maximum speed
andrewboyson 104:46ce1aaf8be7 231 > 10 / ≤ 84 Variable speed from minimum to maximum
andrewboyson 104:46ce1aaf8be7 232 speed
andrewboyson 104:46ce1aaf8be7 233 > 84 / ≤ 91 Minimum speed
andrewboyson 104:46ce1aaf8be7 234 > 91/95 Hysteresis area: on/off
andrewboyson 104:46ce1aaf8be7 235 > 95 / ≤ 100 Standby mode: off
andrewboyson 104:46ce1aaf8be7 236
andrewboyson 104:46ce1aaf8be7 237 Max speed 100 is at fitted = 74; pwm = 10
andrewboyson 104:46ce1aaf8be7 238 Min speed 0 is at fitted = 0; pwm = 84
andrewboyson 104:46ce1aaf8be7 239 */
andrewboyson 104:46ce1aaf8be7 240 int speed = BoilerPumpSpeed;
andrewboyson 104:46ce1aaf8be7 241 if (speed < 0) speed = 0;
andrewboyson 104:46ce1aaf8be7 242 if (speed > 100) speed = 100;
andrewboyson 104:46ce1aaf8be7 243 speed *= 74;
andrewboyson 104:46ce1aaf8be7 244 speed <<= 16;
andrewboyson 104:46ce1aaf8be7 245 speed /= 100;
andrewboyson 104:46ce1aaf8be7 246 speed >>= 16;
andrewboyson 104:46ce1aaf8be7 247 BoilerPumpPwm = 84 - speed;
andrewboyson 104:46ce1aaf8be7 248 }
andrewboyson 104:46ce1aaf8be7 249 #define TIME_BEFORE_TWEAK_SECS 120
andrewboyson 104:46ce1aaf8be7 250 static void tweakDeltaTs()
andrewboyson 104:46ce1aaf8be7 251 {
andrewboyson 104:46ce1aaf8be7 252 static uint32_t msTimerBoilerHeating = 0;
andrewboyson 104:46ce1aaf8be7 253 if (!BoilerCall) msTimerBoilerHeating = MsTimerCount;
andrewboyson 104:46ce1aaf8be7 254 if (!MsTimerRelative(msTimerBoilerHeating, TIME_BEFORE_TWEAK_SECS * 1000)) return;
andrewboyson 104:46ce1aaf8be7 255
andrewboyson 104:46ce1aaf8be7 256 int16_t boilerOutput16ths = DS18B20ValueFromRom(outputRom);
andrewboyson 104:46ce1aaf8be7 257 int16_t boilerReturn16ths = DS18B20ValueFromRom(returnRom);
andrewboyson 104:46ce1aaf8be7 258 int16_t boilerResidual16ths = boilerOutput16ths - boilerReturn16ths;
andrewboyson 104:46ce1aaf8be7 259 bool boilerTempsAreValid = DS18B20IsValidValue(boilerOutput16ths) && DS18B20IsValidValue(boilerReturn16ths);
andrewboyson 104:46ce1aaf8be7 260 if (!boilerTempsAreValid) return;
andrewboyson 104:46ce1aaf8be7 261
andrewboyson 104:46ce1aaf8be7 262 static int speedLastScan = -1;
andrewboyson 104:46ce1aaf8be7 263
andrewboyson 104:46ce1aaf8be7 264 if (speedLastScan == 0 && BoilerPumpSpeed > 0)
andrewboyson 104:46ce1aaf8be7 265 {
andrewboyson 104:46ce1aaf8be7 266 if (rise16thsAt0 > boilerResidual16ths) rise16thsAt0--;
andrewboyson 104:46ce1aaf8be7 267 if (rise16thsAt0 < boilerResidual16ths) rise16thsAt0++;
andrewboyson 104:46ce1aaf8be7 268 }
andrewboyson 104:46ce1aaf8be7 269
andrewboyson 104:46ce1aaf8be7 270 else if (speedLastScan <= 50 && BoilerPumpSpeed > 50)
andrewboyson 104:46ce1aaf8be7 271 {
andrewboyson 104:46ce1aaf8be7 272 if (rise16thsAt50 > boilerResidual16ths) rise16thsAt50--;
andrewboyson 104:46ce1aaf8be7 273 if (rise16thsAt50 < boilerResidual16ths) rise16thsAt50++;
andrewboyson 104:46ce1aaf8be7 274 }
andrewboyson 104:46ce1aaf8be7 275
andrewboyson 104:46ce1aaf8be7 276 else if (speedLastScan < 100 && BoilerPumpSpeed == 100)
andrewboyson 104:46ce1aaf8be7 277 {
andrewboyson 104:46ce1aaf8be7 278 if (rise16thsAt100 > boilerResidual16ths) rise16thsAt100--;
andrewboyson 104:46ce1aaf8be7 279 if (rise16thsAt100 < boilerResidual16ths) rise16thsAt100++;
andrewboyson 104:46ce1aaf8be7 280 }
andrewboyson 104:46ce1aaf8be7 281
andrewboyson 104:46ce1aaf8be7 282 speedLastScan = BoilerPumpSpeed;
andrewboyson 104:46ce1aaf8be7 283 }
andrewboyson 35:bb8a6d1c034c 284 void BoilerMain()
andrewboyson 35:bb8a6d1c034c 285 {
andrewboyson 35:bb8a6d1c034c 286 controlBoilerCall();
andrewboyson 35:bb8a6d1c034c 287 if (BoilerCall) BOILER_CALL_SET;
andrewboyson 35:bb8a6d1c034c 288 else BOILER_CALL_CLR;
andrewboyson 0:3c04f4b47041 289
andrewboyson 35:bb8a6d1c034c 290 controlBoilerPump();
andrewboyson 5:82197a6997fd 291 if (BoilerPump) BOILER_PUMP_SET;
andrewboyson 5:82197a6997fd 292 else BOILER_PUMP_CLR;
andrewboyson 0:3c04f4b47041 293
andrewboyson 104:46ce1aaf8be7 294 controlBoilerPumpSpeed();
andrewboyson 104:46ce1aaf8be7 295 speedToPwm();
andrewboyson 104:46ce1aaf8be7 296 PwmSet(BoilerPumpPwm);
andrewboyson 104:46ce1aaf8be7 297
andrewboyson 104:46ce1aaf8be7 298 tweakDeltaTs();
andrewboyson 104:46ce1aaf8be7 299
andrewboyson 0:3c04f4b47041 300 }