Beer constant set to 21˚C still heating at 22˚C

Just updated to 0.4.4 and also updated the corresponding Tilt hydrometer mods.
Everything seemed to be working fine on 0.4.3.
I finished my Brew but accidentally over chilled the wort with my flat plate chiller and set the brewpi to 21˚C beer constant intending to create a profile this morning.
I was shocked to see it at 22˚C and still heating hence the flurry of changes after 10 am…


I have reset the photon back to defaults and re assigned devices and now put on a profile, which sat idling for 10 minutes but has now started to heat again even though the beer is 2˚c above set temperature…
I’ll just hang on till the fridge gets to it’s set point before I do anything else drastic.

.here are the control Algorithm settings

Controller state as JSON
Refresh

{
  "kind": "Control",
  "pids": [
    {
      "kind": "Pid",
      "name": "heater1",
      "enabled": true,
      "setPoint": {
        "kind": "SetPointSimple",
        "name": "fridgeset",
        "value": 18
      },
      "inputSensor": {
        "kind": "TempSensorFallback",
        "onBackupSensor": false,
        "sensor": {
          "kind": "TempSensor",
          "name": "fridge",
          "sensor": {
            "kind": "OneWireTempSensor",
            "value": 21.875,
            "connected": true,
            "address": "285C83B504000046",
            "calibrationOffset": 0
          }
        }
      },
      "inputError": 3.875,
      "Kp": 10,
      "Ti": 600,
      "Td": 60,
      "p": -38.75,
      "i": 0,
      "d": 3.0859,
      "actuatorIsNegative": false,
      "outputActuator": {
        "kind": "ActuatorPwm",
        "value": 0,
        "period": 4,
        "minVal": 0,
        "maxVal": 100,
        "target": {
          "kind": "ActuatorMutexDriver",
          "mutexGroup": {
            "kind": "ActuatorMutexGroup",
            "deadTime": 1800000,
            "waitTime": 1616513
          },
          "target": {
            "kind": "ActuatorPin",
            "state": false,
            "pin": 10,
            "invert": false
          }
        }
      }
    },
    {
      "kind": "Pid",
      "name": "heater2",
      "enabled": true,
      "setPoint": {
        "kind": "SetPointSimple",
        "name": "beer2set",
        "value": null
      },
      "inputSensor": {
        "kind": "TempSensor",
        "name": "beer2",
        "sensor": {
          "kind": "OneWireTempSensor",
          "value": 12.5,
          "connected": true,
          "address": "28AA4C830400008A",
          "calibrationOffset": 0
        }
      },
      "inputError": null,
      "Kp": 10,
      "Ti": 600,
      "Td": 60,
      "p": 0,
      "i": 0,
      "d": 0,
      "actuatorIsNegative": false,
      "outputActuator": {
        "kind": "ActuatorPwm",
        "value": 0,
        "period": 4,
        "minVal": 0,
        "maxVal": 100,
        "target": {
          "kind": "ActuatorMutexDriver",
          "mutexGroup": {
            "kind": "ActuatorMutexGroup",
            "deadTime": 1800000,
            "waitTime": 1616511
          },
          "target": {
            "kind": "ActuatorNop",
            "state": false
          }
        }
      }
    },
    {
      "kind": "Pid",
      "name": "cooler",
      "enabled": true,
      "setPoint": {
        "kind": "SetPointSimple",
        "name": "fridgeset",
        "value": 18
      },
      "inputSensor": {
        "kind": "TempSensorFallback",
        "onBackupSensor": false,
        "sensor": {
          "kind": "TempSensor",
          "name": "fridge",
          "sensor": {
            "kind": "OneWireTempSensor",
            "value": 21.875,
            "connected": true,
            "address": "285C83B504000046",
            "calibrationOffset": 0
          }
        }
      },
      "inputError": 3.875,
      "Kp": 10,
      "Ti": 1800,
      "Td": 200,
      "p": -38.75,
      "i": 0,
      "d": 10.1953,
      "actuatorIsNegative": true,
      "outputActuator": {
        "kind": "ActuatorPwm",
        "value": 28.5547,
        "period": 1200,
        "minVal": 0,
        "maxVal": 100,
        "target": {
          "kind": "ActuatorMutexDriver",
          "mutexGroup": {
            "kind": "ActuatorMutexGroup",
            "deadTime": 1800000,
            "waitTime": 1616508
          },
          "target": {
            "kind": "ActuatorTimeLimited",
            "minOnTime": 120,
            "minOffTime": 180,
            "maxOnTime": 65535,
            "state": false,
            "target": {
              "kind": "ActuatorPin",
              "state": false,
              "pin": 11,
              "invert": false
            }
          }
        }
      }
    },
    {
      "kind": "Pid",
      "name": "beer2fridge",
      "enabled": false,
      "setPoint": {
        "kind": "SetPointSimple",
        "name": "beer1set",
        "value": null
      },
      "inputSensor": {
        "kind": "TempSensor",
        "name": "beer1",
        "sensor": {
          "kind": "OneWireTempSensor",
          "value": 22.0625,
          "connected": true,
          "address": "28E95857040000CA",
          "calibrationOffset": 0
        }
      },
      "inputError": null,
      "Kp": 2,
      "Ti": 7200,
      "Td": 1200,
      "p": 0,
      "i": 0,
      "d": 0,
      "actuatorIsNegative": false,
      "outputActuator": {
        "kind": "ActuatorSetPoint",
        "targetSetPoint": {
          "kind": "SetPointSimple",
          "name": "fridgeset",
          "value": 18
        },
        "targetSensor": {
          "kind": "TempSensor",
          "name": "fridge",
          "sensor": {
            "kind": "OneWireTempSensor",
            "value": 21.875,
            "connected": true,
            "address": "285C83B504000046",
            "calibrationOffset": 0
          }
        },
        "referenceSetPoint": {
          "kind": "SetPointSimple",
          "name": "beer1set",
          "value": null
        },
        "output": 127.9961,
        "achieved": 127.9961,
        "minimum": -10,
        "maximum": 10
      }
    }
  ]
}

edit

changed the following to see how it behaves

Beer-to-Fridge proportional gain (Kp)= 8

Beer-to-Fridge integral time constant (Ti)=10200

Beer-to-Fridge derivative time constant (Td)=600

not sure but how feasible is it to incorporate a Tuning function to determine your initial PID settings
ie place a container with a known qty of liquid say 20 L, measure the time to raise it a set temperature then do the same to cool it and from that work out your PID variables…

The JSON output that you posted is from after when you started/reset the settings, so it doesn’t help me address the overshoot. So I base this analysis off the cart that you posted.

I see that your fridge setpoint is high and the fridge temp can just not reach it. You have integrator windup in the period where the fridge setpoint is below the limit, but still not reaching it.

What is happening in your chart:

– Your beer to fridge Kp is way too low. This causes the integrator to do the work that the proportional part should do, causing unnecessary windup. Increase beer-to-fridge Kp to for example 10. This will also cause the setpoint of the fridge to decrease much quicker. You can see it like this: with a very low Kp, the integrator is doing all the work. The integrator is very slow to respond (by design).
– You should also decrease the beer to fridge max difference, so your fridge setpoint clips to a lower value. As long as it is clipped to max, the integrator is held at zero. Clipping it to a lower value will not do you any harm, as you are not reaching the setpoint anyway. You seem to not be able to reach a fridge temperature more than 5 degrees above the beer temperature. So set the max difference to 5.

I hope this helps. You definitely should be using 0.4.4, there are stability and integrator anti-windup improvements in it that you really want to have.

thanks Elco, after my initial panic and then reading some of the other forum posts I changed it to a KP of 8 and on seeing your reply today changed the max difference to 5 ˚C.
I am considering upping the heater output but if I do i’ll test before another ferment. Is it an option to add a calibration routine to run prior to a fermentation run to roughly set your PID variables for ones own chamber setup or is that too complex to implement ?