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

Revision:
106:41ed3ea0bbba
Parent:
105:1899f7ed17ec
--- a/heating/boiler.c	Tue Feb 23 20:35:07 2021 +0000
+++ b/heating/boiler.c	Fri Apr 23 08:36:42 2021 +0000
@@ -22,7 +22,6 @@
 #define PUMP_SPEED_CALLING_AUTO_ONLY  -1
 #define PUMP_SPEED_CALLING_AUTO_TWEAK -2
 
-#define MIN_SPEED  40
 #define MAX_SPEED 100
 
 static char*     tankRom; static int iTankRom;
@@ -33,16 +32,16 @@
 
 static int8_t  tankSetPoint;       static int iTankSetPoint;
 static int16_t tankHysteresis;     static int iTankHysteresis;
-static int16_t runOnResidual16ths; static int iRunOnResidual;
+static int16_t _runOnDelta16ths; static int iRunOnResidual;
 static uint8_t runOnTime2s;        static int iRunOnTime;
 
 static int8_t  boilerTarget;       static int iBoilerTarget;
 static int8_t  pumpSpeedCalling;   static int iPumpSpeedCalling;
-static int8_t  pumpSpeedRunOn;     static int iPumpSpeedRunOn;
+static int8_t  _rampDownTime;     static int _iRampDownTime;
 
-static int16_t rise16thsAt0;       static int iRiseAt0;
-static int16_t rise16thsAt50;      static int iRiseAt50;
-static int16_t rise16thsAt100;     static int iRiseAt100;
+static int8_t  _minSpeed;             static int _iMinSpeed;
+static int8_t  _midSpeedPwm;          static int _iMidSpeedPwm;
+static int16_t _fullSpeedDeltaT16ths; static int _iFullSpeedDeltaT;
 
 //Set in main scan
 static int16_t _boilerOutput16ths   = DS18B20_ERROR_VALUE_NOT_SET;
@@ -52,36 +51,36 @@
 static bool    _boilerDeltaTisValid = false;
 
 int16_t  BoilerGetTankDS18B20Value  () { return DS18B20ValueFromRom(tankRom);   } 
-int16_t  BoilerGetOutputDS18B20Value() { return _boilerOutput16ths; } 
-int16_t  BoilerGetReturnDS18B20Value() { return _boilerReturn16ths; }
-int16_t  BoilerGetRtnDelDS18B20Value() { return _boilerRtnDel16ths; }
-int16_t  BoilerGetDeltaTDS18B20Value() { return _boilerDeltaT16ths; } 
-int      BoilerGetFullSpeedSecs     () { return fullSpeedSecs;      }
-int      BoilerGetTankSetPoint      () { return tankSetPoint;       }
-int      BoilerGetTankHysteresis    () { return tankHysteresis;     } 
-int      BoilerGetRunOnDeltaT       () { return runOnResidual16ths; }
-int      BoilerGetRunOnTime         () { return runOnTime2s << 1;   }
-int      BoilerGetPumpSpeedCalling  () { return pumpSpeedCalling;   }
-int      BoilerGetPumpSpeedRunOn    () { return pumpSpeedRunOn;     }
-int      BoilerGetOutputTarget      () { return boilerTarget;       }
-int      BoilerGetMinimumFlow       () { return rise16thsAt0;       }
-int      BoilerGetMidFlowSpeed      () { return rise16thsAt50;      }
-int      BoilerGetFullSpeedDeltaT   () { return rise16thsAt100;     }
+int16_t  BoilerGetOutputDS18B20Value() { return _boilerOutput16ths;    } 
+int16_t  BoilerGetReturnDS18B20Value() { return _boilerReturn16ths;    }
+int16_t  BoilerGetRtnDelDS18B20Value() { return _boilerRtnDel16ths;    }
+int16_t  BoilerGetDeltaTDS18B20Value() { return _boilerDeltaT16ths;    } 
+int      BoilerGetFullSpeedSecs     () { return fullSpeedSecs;         }
+int      BoilerGetTankSetPoint      () { return tankSetPoint;          }
+int      BoilerGetTankHysteresis    () { return tankHysteresis;        } 
+int      BoilerGetRunOnDeltaT       () { return _runOnDelta16ths;      }
+int      BoilerGetRunOnTime         () { return runOnTime2s << 1;      }
+int      BoilerGetPumpSpeedCalling  () { return pumpSpeedCalling;      }
+int      BoilerGetRampDownTime      () { return _rampDownTime;        }
+int      BoilerGetOutputTarget      () { return boilerTarget;          }
+int      BoilerGetMinSpeed          () { return _minSpeed;             }
+int      BoilerGetMidSpeedPwm       () { return _midSpeedPwm;          }
+int      BoilerGetFullSpeedDeltaT   () { return _fullSpeedDeltaT16ths; }
 
-static void setTankRom          (char* value) { memcpy(tankRom,      value, 8); FramWrite(iTankRom,         8,  tankRom            ); }
-static void setOutputRom        (char* value) { memcpy(outputRom,    value, 8); FramWrite(iOutputRom,       8,  outputRom          ); }
-static void setReturnRom        (char* value) { memcpy(returnRom,    value, 8); FramWrite(iReturnRom,       8,  returnRom          ); }
-void BoilerSetFullSpeedSecs     (int   value) { fullSpeedSecs      = value;     FramWrite(iFullSpeedSecs,   1, &fullSpeedSecs      ); }
-void BoilerSetTankSetPoint      (int   value) { tankSetPoint       = value;     FramWrite(iTankSetPoint,    1, &tankSetPoint       ); }
-void BoilerSetTankHysteresis    (int   value) { tankHysteresis     = value;     FramWrite(iTankHysteresis,  2, &tankHysteresis     ); }
-void BoilerSetRunOnDeltaT       (int   value) { runOnResidual16ths = value;     FramWrite(iRunOnResidual,   2, &runOnResidual16ths ); }
-void BoilerSetRunOnTime         (int   value) { runOnTime2s        = value >> 1;FramWrite(iRunOnTime,       1, &runOnTime2s        ); }
-void BoilerSetPumpSpeedCalling  (int   value) { pumpSpeedCalling   = value;     FramWrite(iPumpSpeedCalling,1, &pumpSpeedCalling   ); }
-void BoilerSetPumpSpeedRunOn    (int   value) { pumpSpeedRunOn     = value;     FramWrite(iPumpSpeedRunOn,  1, &pumpSpeedRunOn     ); }
-void BoilerSetOutputTarget      (int   value) { boilerTarget       = value;     FramWrite(iBoilerTarget,    1, &boilerTarget       ); }
-void BoilerSetMinimumFlow       (int   value) { rise16thsAt0       = value;     FramWrite(iRiseAt0,         2, &rise16thsAt0       ); }
-void BoilerSetMidFlowSpeed      (int   value) { rise16thsAt50      = value;     FramWrite(iRiseAt50,        2, &rise16thsAt50      ); }
-void BoilerSetFullSpeedDeltaT   (int   value) { rise16thsAt100     = value;     FramWrite(iRiseAt100,       2, &rise16thsAt100     ); }
+static void setTankRom          (char* value) { memcpy(tankRom,         value, 8); FramWrite(iTankRom,         8,  tankRom              ); }
+static void setOutputRom        (char* value) { memcpy(outputRom,       value, 8); FramWrite(iOutputRom,       8,  outputRom            ); }
+static void setReturnRom        (char* value) { memcpy(returnRom,       value, 8); FramWrite(iReturnRom,       8,  returnRom            ); }
+void BoilerSetFullSpeedSecs     (int   value) { fullSpeedSecs         = value;     FramWrite(iFullSpeedSecs,   1, &fullSpeedSecs        ); }
+void BoilerSetTankSetPoint      (int   value) { tankSetPoint          = value;     FramWrite(iTankSetPoint,    1, &tankSetPoint         ); }
+void BoilerSetTankHysteresis    (int   value) { tankHysteresis        = value;     FramWrite(iTankHysteresis,  2, &tankHysteresis       ); }
+void BoilerSetRunOnDeltaT       (int   value) { _runOnDelta16ths      = value;     FramWrite(iRunOnResidual,   2, &_runOnDelta16ths     ); }
+void BoilerSetRunOnTime         (int   value) { runOnTime2s           = value >> 1;FramWrite(iRunOnTime,       1, &runOnTime2s          ); }
+void BoilerSetPumpSpeedCalling  (int   value) { pumpSpeedCalling      = value;     FramWrite(iPumpSpeedCalling,1, &pumpSpeedCalling     ); }
+void BoilerSetRampDownTime      (int   value) { _rampDownTime         = value;     FramWrite(_iRampDownTime,   1, &_rampDownTime        ); }
+void BoilerSetOutputTarget      (int   value) { boilerTarget          = value;     FramWrite(iBoilerTarget,    1, &boilerTarget         ); }
+void BoilerSetMinSpeed          (int   value) { _minSpeed             = value;     FramWrite(_iMinSpeed,       1, &_minSpeed            ); }
+void BoilerSetMidSpeedPwm       (int   value) { _midSpeedPwm          = value;     FramWrite(_iMidSpeedPwm,    1, &_midSpeedPwm         ); }
+void BoilerSetFullSpeedDeltaT   (int   value) { _fullSpeedDeltaT16ths = value;     FramWrite(_iFullSpeedDeltaT,2, &_fullSpeedDeltaT16ths); }
 
 static int calculateBetweenTwoPoints(int x, int xA, int xB, int yA, int yB)
 {
@@ -90,24 +89,15 @@
 }
 static int calculateSpeedFromDeltaT(int deltaT16ths)
 {
-    if (deltaT16ths < rise16thsAt100) return MAX_SPEED; //Needed in case deltaT16ths is negative or zero
-    int flow = MAX_SPEED * rise16thsAt100 / deltaT16ths; //eg for 20 deg ==> 100 * (10 << 4) / (20 << 4) == 50
-    if (flow > MAX_SPEED) flow = MAX_SPEED;
-    if (flow < MIN_SPEED) flow = MIN_SPEED;
-    return flow;
-    
-    //if      (deltaT16ths > rise16thsAt0  ) return MIN_SPEED;
-    //else if (deltaT16ths > rise16thsAt50 ) return calculateBetweenTwoPoints(deltaT16ths, rise16thsAt50,  rise16thsAt0,  MID_SPEED, MIN_SPEED);
-    //else if (deltaT16ths > rise16thsAt100) return calculateBetweenTwoPoints(deltaT16ths, rise16thsAt100, rise16thsAt50, MAX_SPEED, MID_SPEED);
-    //else                                   return MAX_SPEED;
+    if (deltaT16ths < _fullSpeedDeltaT16ths) return MAX_SPEED;   //Needed in case deltaT16ths is negative or zero
+    int speed = MAX_SPEED * _fullSpeedDeltaT16ths / deltaT16ths; //eg for 20 deg ==> 100 * (10 << 4) / (20 << 4) == 50
+    if (speed > MAX_SPEED) speed = MAX_SPEED;
+    if (speed < _minSpeed) speed = _minSpeed;
+    return speed;
 }
 static int calculateDeltaTFromSpeed(int speed)
 {
-    int deltaT16ths = MAX_SPEED * rise16thsAt100 / speed; //eg for speed = 50 ==> 100 * (10 << 4) / 50 == 20 << 4
-    //if      (speed >= MAX_SPEED) return rise16thsAt100;
-    //else if (speed >  MID_SPEED) return calculateBetweenTwoPoints(speed, MID_SPEED, MAX_SPEED, rise16thsAt50, rise16thsAt100);
-    //else if (speed >  MIN_SPEED) return calculateBetweenTwoPoints(speed, MIN_SPEED, MID_SPEED, rise16thsAt0,  rise16thsAt50 );
-    //else                         return rise16thsAt0;
+    int deltaT16ths = MAX_SPEED * _fullSpeedDeltaT16ths / speed; //eg for speed = 50 ==> 100 * (10 << 4) / 50 == 20 << 4
     return deltaT16ths;
 }
 
@@ -132,20 +122,22 @@
     uint8_t def1;
     int16_t def2;
     int32_t def4;
-                  address = FramLoad( 8,  tankRom,                0); if (address < 0) return -1; iTankRom          = address;
-                  address = FramLoad( 8,  outputRom,              0); if (address < 0) return -1; iOutputRom        = address;
-                  address = FramLoad( 8,  returnRom,              0); if (address < 0) return -1; iReturnRom        = address;
-    def1 =   100; address = FramLoad( 1, &fullSpeedSecs,      &def1); if (address < 0) return -1; iFullSpeedSecs    = address;
-    def1 =    65; address = FramLoad( 1, &tankSetPoint,       &def1); if (address < 0) return -1; iTankSetPoint     = address;
-    def2 =     5; address = FramLoad( 2, &tankHysteresis,     &def2); if (address < 0) return -1; iTankHysteresis   = address;
-    def2 =     2; address = FramLoad( 2, &runOnResidual16ths, &def2); if (address < 0) return -1; iRunOnResidual    = address;
-    def1 =   180; address = FramLoad( 1, &runOnTime2s,        &def1); if (address < 0) return -1; iRunOnTime        = address;
-    def1 =   100; address = FramLoad( 1, &pumpSpeedCalling,   &def1); if (address < 0) return -1; iPumpSpeedCalling = address;
-    def1 =    10; address = FramLoad( 1, &pumpSpeedRunOn,     &def1); if (address < 0) return -1; iPumpSpeedRunOn   = address;
-    def1 =    65; address = FramLoad( 1, &boilerTarget,       &def1); if (address < 0) return -1; iBoilerTarget     = address;
-    def2 = 10<<4; address = FramLoad( 2, &rise16thsAt0,       &def2); if (address < 0) return -1; iRiseAt0          = address;
-    def2 = 15<<4; address = FramLoad( 2, &rise16thsAt50,      &def2); if (address < 0) return -1; iRiseAt50         = address;
-    def2 = 20<<4; address = FramLoad( 2, &rise16thsAt100,     &def2); if (address < 0) return -1; iRiseAt100        = address;
+                  address = FramLoad( 8,  tankRom,                   0); if (address < 0) return -1; iTankRom          = address;
+                  address = FramLoad( 8,  outputRom,                 0); if (address < 0) return -1; iOutputRom        = address;
+                  address = FramLoad( 8,  returnRom,                 0); if (address < 0) return -1; iReturnRom        = address;
+    def1 =   100; address = FramLoad( 1, &fullSpeedSecs,         &def1); if (address < 0) return -1; iFullSpeedSecs    = address;
+    def1 =    65; address = FramLoad( 1, &tankSetPoint,          &def1); if (address < 0) return -1; iTankSetPoint     = address;
+    def2 =     5; address = FramLoad( 2, &tankHysteresis,        &def2); if (address < 0) return -1; iTankHysteresis   = address;
+    def2 =     2; address = FramLoad( 2, &_runOnDelta16ths,      &def2); if (address < 0) return -1; iRunOnResidual    = address;
+    def1 =   180; address = FramLoad( 1, &runOnTime2s,           &def1); if (address < 0) return -1; iRunOnTime        = address;
+    def1 =   100; address = FramLoad( 1, &pumpSpeedCalling,      &def1); if (address < 0) return -1; iPumpSpeedCalling = address;
+    def1 =    10; address = FramLoad( 1, &_rampDownTime,        &def1); if (address < 0) return -1; _iRampDownTime   = address;
+    def1 =    65; address = FramLoad( 1, &boilerTarget,          &def1); if (address < 0) return -1; iBoilerTarget     = address;
+    def1 =    50; address = FramLoad( 1, &_minSpeed,             &def1); if (address < 0) return -1; _iMinSpeed        = address;
+                            FramAllocate(1);
+    def1 =    50; address = FramLoad( 1, &_midSpeedPwm,          &def1); if (address < 0) return -1; _iMidSpeedPwm     = address;
+                            FramAllocate(1);
+    def2 = 10<<4; address = FramLoad( 2, &_fullSpeedDeltaT16ths, &def2); if (address < 0) return -1; _iFullSpeedDeltaT = address;
     
     BOILER_PUMP_DIR = 1; //Set the direction to 1 == output
     BOILER_CALL_DIR = 1; //Set the direction to 1 == output
@@ -187,12 +179,12 @@
     }
     else
     {
-        if (MsTimerRelative(msTimerBoilerPumpRunOn,      runOnTime2s * 2000)) BoilerPump = false;
-        if (_boilerDeltaTisValid && _boilerDeltaT16ths < runOnResidual16ths ) BoilerPump = false;
+        if (MsTimerRelative(msTimerBoilerPumpRunOn,    runOnTime2s * 2000)) BoilerPump = false;
+        if (_boilerDeltaTisValid && _boilerDeltaT16ths < _runOnDelta16ths ) BoilerPump = false;
     }
 }
-int BoilerPumpFlow  = MIN_SPEED;
-int BoilerPumpSpeed = MIN_SPEED;
+int BoilerPumpFlow  = MAX_SPEED;
+int BoilerPumpSpeed = MAX_SPEED;
 int BoilerPumpPwm   = 0;
 static int _autoSpeed = 0;
 static void calculateAutoSpeed()
@@ -210,28 +202,29 @@
     calculateAutoSpeed();
     if (BoilerCall)
     {
-        if (pumpSpeedCalling > MAX_SPEED || pumpSpeedCalling < MIN_SPEED) BoilerPumpSpeed = _autoSpeed;        //Auto
-        else                                                              BoilerPumpSpeed = pumpSpeedCalling;  //Manual
+        if (pumpSpeedCalling < 0) BoilerPumpSpeed = _autoSpeed;        //Auto
+        else                      BoilerPumpSpeed = pumpSpeedCalling;  //Manual
         msTimerReduction = MsTimerCount;
     }
     else
     {
-        if (BoilerPumpSpeed > pumpSpeedRunOn)
+        if (BoilerPumpSpeed > _minSpeed)
         {
-            if (MsTimerRepetitive(&msTimerReduction, 250)) BoilerPumpSpeed--;
+            int msPerUnit = 1000 * _rampDownTime / (MAX_SPEED - _minSpeed);
+            if (MsTimerRepetitive(&msTimerReduction, msPerUnit)) BoilerPumpSpeed--;
         }
         else
         {
-            BoilerPumpSpeed = pumpSpeedRunOn;
+            BoilerPumpSpeed = _minSpeed;
         }
     }
+    if (BoilerPumpSpeed < _minSpeed) BoilerPumpSpeed = _minSpeed;
+    if (BoilerPumpSpeed > MAX_SPEED) BoilerPumpSpeed = MAX_SPEED;
 }
-static void flowToSpeed()
+static int speedToPwm(int speed)
 {
-    //Do nothing yet
-}
-static void speedToPwm()
-{
+    #define MAX_SPEED_PWM 10
+    #define MIN_SPEED_PWM 84
     /*
     PWM input signal [%] Pump status
     ≤ 10 Maximum speed
@@ -244,10 +237,15 @@
     Max speed 100 is at fitted = 74; pwm = 10
     Min speed   0 is at fitted =  0; pwm = 84
     */
-    int pwm = calculateBetweenTwoPoints(BoilerPumpSpeed, MIN_SPEED, MAX_SPEED, 84, 10);
-    if (pwm < 10) pwm = 10;
-    if (pwm > 84) pwm = 84;
-    BoilerPumpPwm = pwm;
+    if (speed <= _minSpeed) return MIN_SPEED_PWM;
+    if (speed >= MAX_SPEED) return MAX_SPEED_PWM;
+    int midSpeed = (_minSpeed + MAX_SPEED) / 2;
+    if (speed < midSpeed) return calculateBetweenTwoPoints(speed, _minSpeed,  midSpeed, MIN_SPEED_PWM,   _midSpeedPwm);
+    else                  return calculateBetweenTwoPoints(speed,  midSpeed, MAX_SPEED,  _midSpeedPwm,  MAX_SPEED_PWM);
+    //int pwm = calculateBetweenTwoPoints(BoilerPumpSpeed, _minSpeed, MAX_SPEED, 84, 10);
+    //if (pwm < 10) pwm = 10;
+    //if (pwm > 84) pwm = 84;
+    //BoilerPumpPwm = pwm;
 }
 #define TIME_BEFORE_TWEAK_SECS 120
 static void tweakDeltaTs()
@@ -264,8 +262,8 @@
     
     if (speedLastScan < MAX_SPEED && BoilerPumpSpeed == MAX_SPEED)
     {
-        if (rise16thsAt100 > _boilerDeltaT16ths) rise16thsAt100--;
-        if (rise16thsAt100 < _boilerDeltaT16ths) rise16thsAt100++;
+        if (_fullSpeedDeltaT16ths > _boilerDeltaT16ths) _fullSpeedDeltaT16ths--;
+        if (_fullSpeedDeltaT16ths < _boilerDeltaT16ths) _fullSpeedDeltaT16ths++;
     }
     
     speedLastScan = BoilerPumpSpeed;
@@ -365,8 +363,7 @@
     else            BOILER_PUMP_CLR;
     
     controlBoilerPumpSpeed();
-    flowToSpeed();
-    speedToPwm();
+    BoilerPumpPwm = speedToPwm(BoilerPumpSpeed);
     PwmSet(BoilerPumpPwm);
     
     tweakDeltaTs();