craigmw / CellarWarden

A wine/beer cellar temperature/humidity monitoring and control app for the Raspberry Pi
32 stars 4 forks source link

PID auto-tuning stuck #7

Closed iverberk closed 7 years ago

iverberk commented 7 years ago

I've tried several times to use the PID auto-tuning to get a preliminary set of parameters but each time it fails to complete. I used the following settings: http://pasteboard.co/6TCiCbVVt.png

I've started it yesterday evening and let it run all night. This is the result: http://pasteboard.co/6TyN5mUSt.png

At first it warms up to the set temperature (28 degrees) and then it starts to cool. After a while it decides that it needs to heat up again. I see AH heating appearing in the LCD but the relay is never switched on again, hence the continuing decline in temperature.

I'm not sure if this is user error or that something is wrong with the algorithm/hardware control. I tried it twice and every time the heating stops and the algorithm never finishes.

Any ideas/suggestions?

craigmw commented 7 years ago

It appears that the autotuning algorithm was cycling the cooling actuator instead of the heating actuator. I think this could be due to it setting the wrong values for cooling vs. heating output levels during the autotune cycling. The autotuning cycle also appears to have run about 4 hours from 22:00 (April 20) to 02:00 (April 21) and then finished. Did it provide Kp, Ki and Kd values in the server log file? These should also show up in the fields for those parameters in the controller configuration dialog.

I'll need to do some testing on this if I can find the time over the weekend.

iverberk commented 7 years ago

Ah, it did actually finish: Fri Apr 21 2017 15:03:01 GMT+0200 (CEST): Autotuning completed Autotuning cancelled. Preliminary values - Kp: 1.9757181387795217 Ki: 0.0006147727183005836 Kd: 1587.3598680064883

The date is probably a misconfiguration on my RPi. I'm sure that the GPIO configuration is correct for the heating and cooling actuator. Not sure how useful the values are if the algorithm is reversing the actuators.

craigmw commented 7 years ago

I don't think it's reversing the actuators, it just appears that the starting output values were off. I know that there is a bug in that part of the logic. Basically, the AT routine takes the current output value and then it (should) bump it up by 30 for heating, and down 30 for cooling. If the output was at 50% when started, the AT algorithm should shift the heating output to 80 for a while and then switch cooling to 20%. This should result in a cycling of the PV until it can determine the distance between the peaks, which it uses to calculated the Kp, Ki and Kd values. It appears from your graph that the cooling actuator output was set properly, but not the heating output level. I'll have to check into this.

iverberk commented 7 years ago

Thanks for the explanation Craig. I'll await your findings and let me know if I can test anything for you :-)

craigmw commented 7 years ago

Ivo:

I've done a bunch of testing this weekend using the autotuner and it seems to be working okay on my crude setup. I have a waterproof DS18B20 sitting in a small slow cooker filled with water. First, I use the stock PID values and let the system come to "homeostasis" with the stock PID values (e.g. the temperature is stable near the set point). After the system has been running near the set point for some time, I click on the Autotune button and let it run. In my case, it takes about two hours to complete the auto tuning, and the values are a bit aggressive, particularly the D gain (about 3000-5000). These values give a fairly stable PV (water temp), but the output values are a bit crazy. I back off the D gain to about 50 and this gives a fairly very response with the output and PV quite stable over time. Adding cold water to disturb the system leads to a fairly controlled return of the PV to the setpoint. Note that many systems are controlled by PI only controllers, so I don't feel guilty adjusting the gain down so significantly. PID autotuning is by its nature an imperfect method, so human input can always lead to better values.

I was incorrect about my initial description. When the system is stable, starting the autotune shifts the output by 20 for both the heating and cooling parameter. Say your system was stable at about 30%. When you hit the Autotune button for heating, the output will shift to 50% for heating and 10% for cooling (+/- 20%). It will then oscillate this value for several times until the period of oscillation is within 5% for each cycle, or if it does more than 9 oscillations. It will then complete the autotuning and provide P, I and D gain parameters automatically filled in in the controller dialog for the heating actuator. Note that the set point is taken from the PV at the time that the autotune routine was started, not the desired SP. For this reason, it's best to get the PV as close to the SP as possible before starting the routine. I will also note that the autotuning routine might produce numbers higher than the system might handle (e.g. +100% for heating, -100% for cooling), but the system will account for this even if the plots might look strange.

The auto tuning algorithm that CellarWarden uses is designed to tweak the values to give a better response, but cannot adequately account for a system that is inherently unstable. The heating appliance needs to provide enough heat circulated in the chamber to be able to change rapidly enough for the controller to accurately respond. If the heat is not radiated rapidly enough, the temperature will likely overshoot. You may be able to adjust the PID values to accommodate this.

I would suggest adding a fan to your system to adequately circulate the heat radiated from the heater tube through the chamber to the probe. In a typical wine cellar, the cooling units have built-in fans that circulate the cooled air throughout the system, which provides a reasonable responsiveness. The fan can be wired to activate when the heater is on, which would help to circulate this and keep it from being on all the time. Alternatively, a heating mat (e.g. FermWrap or reptile heater mat) at the bottom of the chamber might lead to better convective heating of the chamber.

While the CellarWarden PID autotuning algorithm seems to be functioning properly, there are some things that could be improved. First, the algorithm seems to call for an initial increase in output level, even if tuning the cooling actuator. I will need to adjust the logic so that it accounts for the type of actuator (PID on two actuators is complicated enough; doing autotuning like this is really racking my brain!). Second, I need to fix the logic so that it doesn't overshoot the +100 to -100% range limited by the actuator logic. It's not an issue because the actuator logic automatically accounts for out of range values, but it tends to mess up the log file display. Lastly, I intend to incorporate some fuzzy logic so that the autotuning can use a method that provides P, I and D values more quickly based on the change in PV for a given output value. I'm not a controls engineer, so this may take some examination into an area I'm not familiar with.

In summary, my recommendations are to:

  1. Add a fan to your chamber to recirculate the air for quicker response times.
  2. Let the system achieve homeostasis (e.g. stable temperature near the set point).
  3. Run the autotune routine with the understanding that the values may not be perfect. Some tweaking of the gain values may be necessary to optimize the response for your particular application.
craigmw commented 7 years ago

Incidentally, your system should be able to have a reasonable response using hysteresis control. If you can achieve a fairly stable PV for a given setpoint in hysteresis mode, PID mode can give a better response, particularly after tuning the PID. There will be some over- and under-shooting with hysteresis mode, as this is the nature of that sort of control method. In my experience, if the PID loop is significantly out of tune, it can result in overshooting the setpoint and oscillation. Proper tuning will minimize this. However, it cannot fix problems with the basic system design. If you cannot achieve a "reasonable" variation in PV using hysteresis mode, it may be necessary to work on the system (e.g. increase heating capacity, air circulation, etc).

The other thing to consider is that the chamber may experience some variation in temperature or humidity given the lag in output vs. PV (temp or humidity). However, if you measure the target (bread dough in this case), it's probably acceptable. I would imagine that the internal temperature of the dough to be quite stable since it will have a higher heat capacity than air. I observe much larger variation in the air temperature of my wine cabinet and beer fermentation chamber than the liquid temperature of my wine bottles or fermenting beer, respectively.

Hopefully, this is helpful. I really think your application is very interesting! I would really like to know how this impacts your final product, excellent bread!

Craig

iverberk commented 7 years ago

HI Craig,

Thanks for your elaborate response. I've mounted two fans in the freezer to circulate the air and will try the auto-tuning mechanism again, taking all the considerations you mentioned into account. I really appreciate your help with this. I'll update this ticket to let you know how it goes. It might take some time to go through all the cycles :-)

craigmw commented 7 years ago

Ivo:

In my tests, the AT routine seems to work well, but the test system is different than your application. For one, my system is based on heated water which has a more stable response than heated/cooled air. Secondly, I'm really just using a single actuator (heater) which simplifies the AT process. With two actuators (fridge compressor and heater tube) in your system, it's going to be more complicated. The PID algorithm supports two-sided control. As the PV (temp) nears the setpoint while heating, the output nears zero. If it goes above the setpoint, it will start to increment the cooling actuator output. Since they are two different actuator types with different response times (particularly since your compressor should not be rapidly cycled), there will be different tuning parameters for cooling vs. heating.

In the case of a one-sided system as in my test setup, the heating is controlled whereas the cooling occurs naturally (as a function of Newton's law of cooling). The AT routine used (Ziegler-Nichols) accounts for this since it cycles through heating and cooling phases. However, with a 2-sided control, this won't be the case if only one actuator is off. So, given more thinking about this, it might be desirable to leave both actuators active and let the Z-N tuning account for this and then use the same PID tuning parameters that are calculated. So, using the following parameters in PID mode:

Cooling: Delay (5min), PID Window Size (300), Kp (2.5), Ki (0.0035), Kd (6) Heating: Delay (0), PID Window Size (4), Kp (2.5), Ki (0.0035), Kd (6)

Assign both GPIO pins so that both the heating and cooling actuator can be controlled by CellarW. Set your SP to a value at roughly the center point of the range you wish to control, then start the controller (e.g. make sure the Active checkbox is checked). The system may take some time to achieve a stable response, since the system will not be properly tuned. Note the output needed to come to a fairly stable PV. It should be somewhere between -80 to 80%. After the system has achieved a stable output and PV, run the heating actuator autotuning.

An alternative method that is quicker and can give values close to the Z-N method CellarW employs is the Cohen-Coon autotuning method. You can do this manually by following instructions here:

http://www.controleng.com/single-article/tuning-pid-control-loops-for-fast-response/495b3c78823d6ccfa58f2f83d58dc85c.html

I've tried this method and it does give values comparable to what CellarW calculates and in a much faster manner. If I can figure out how to code it, I will include it as an autotuning option in CellarW. It might also be more suited to individually tuning the heating vs. cooling PID parameters.

iverberk commented 7 years ago

I've just finished some tests last night with maintaining temperatures below ambient. I've added two fans and put in a second thermometer that I put in a bowl of water. The water is there to provide thermal mass since the air alone will just fluctuate rapidly. So far I've been able to maintain a fairly constant temperature by just using hysteresis alone and taking the reading of the secondary thermometer into account. I've disabled the heater in this case because the ambient temperature is going to bring up the temperature quite steadily, adding additional heating is just going to overshoot it. I don't think I'll be using PID when I want to cool because most likely it will lead to additional cycling of the compressor with relatively little gain in terms of temperature stability.

Right now I'm going to test the heating, for which I am looking to use the PID algorithm. I'm now getting the room and water up to the temperature (28 degrees) that I want and will start the AT from there. After that I will also test your latest suggestions and see if I can come to an optimal setting.

So far, adding a big bowl of water and a secondary temperature has resulted in a fairly stable response when cooling with which I'm pretty happy. I'm sure I'll be able to figure something out for the heating.

Lastly I will probably start looking into the temperature profiles to just pre-program a temperature curve that corresponds with the required dough proofing time/temperatures. I'll do this once I really learn what the lag in the system is and how well it behaves. I'll post further updates when I've got the heating down. Thanks for all your efforts!!

craigmw commented 7 years ago

Currently, CellarW doesn't support hysteresis and PID on the same controller. You would have to enable a separate cooling controller using hysteresis mode. This would work, but since controllers follow their own setpoint profiles, it might be difficult to implement this the way you would want. I may change this in a future update, but I'm not quite sure how the PID would respond in this case.

iverberk commented 7 years ago

hmm ok, I'll have to think about it a little more but so far having active cooling and heating on the same controller seems to present more problems in terms of temperature stability (overshoot) than just having two controllers and letting them heat up or cool down by natural pull towards ambient temperature. Of course this makes it harder to automate like you said, but this will give me far more control over fermentation/proofing temperatures than I ever had before anyway, so a little manual adjusting is ok :-) First up is seeing the PID in action with just heating (cooling actuator disabled) to see what it is capable of. Then I will try to tune the system with both heating and cooling on the same controller. After I'll decide what the best approach will be in terms of automation and stability. It's a pretty interesting process that I didn't anticipate when I started this little project :D

iverberk commented 7 years ago

oh btw, I've also been adjusting the secondary sensor input weight over time. This is also something that you might want to automate because sometimes you want more effect from the air temperature and later on, when the thermal mass has reached the SP, you will want to keep it there and let that temperature sensor take more control of the heating and cooling. I've done this process manually for the cooling and it resulted in really nice cycle times (cooling switched on about every 1.5h) while keeping the thermal mass within 0.5 degrees of the setpoint (air temperature varied a lot more but also not extreme and that doesn't matter much).

craigmw commented 7 years ago

I think you will probably find that getting the heating and cooling actuators properly tuned will give a good overall response, particularly with respect to the thermal mass you are interested in, but this will take some tweaking. I think the idea of adaptively adjusting the sensor priority based on how close PV is to the setpoint is an interesting idea. I'm not sure how the PID controller would respond, since the tuning would be affected by the differences in cycling times. I do see how it could give a very stable effect near the desired setpoint. I'm sure there must be plenty out there in control theory regarding this. I'll have to do a little reading!

If I'm understanding your logic, you would increase sensor priority toward the air sensor when the difference between the dough temperature and SP is high, but then increase priority toward the dough sensor when its temperature is close to PV?

iverberk commented 7 years ago

Hi Craig,

I must be doing something wrong. I followed your procedure. I added the fans and let the system achieve homeostasis around 29 degrees Celsius. These are the results so far: http://pasteboard.co/9NqNwR2wc.png and http://pasteboard.co/9NreuUkP3.png. It has been heating up for over an hour and it reached a temperature that I was not comfortable with anymore. Do I need to set a lower setpoint or what can I expect? I would assume that it heats up a little and then starts cooling, not continuous heating. Any pointers?

iverberk commented 7 years ago

btw this is with the second sensor mixed in at 50%. Inside mass and air were about equal temperatures when I started.

craigmw commented 7 years ago

Ivo:

I can't really tell from the graph when you started the AT routine, but it appears that the output was already at 100% when this was done. Autotune is not going to work at this range, as it needs to be in a range where heating or cooling is less that 80%, so that might explain why it seems to be uncontrolled. I'm uncertain about why the system goes out of control though. It should normally search for a peak or valley in the PV of about 1 degree C and then shift to the opposite actuator. This might be due to what the routine thinks is noise on the PV because it was not stable near the setpoint at the time the AT routine was run.

Is there a way for you to get the output stable first? The default PID parameters will not be optimal for your system, but they should eventually give you a stable PV. If wildly untuned, you could get oscillations of the PV around the setpoint, but decreasing the I and increasing the D gains should prevent oscillation eventually.

As I mentioned, another approach to derive these terms would be to use the Cohen-Coon method described in the link I sent you. This will take much less time than running the Ziegler-Nichols relay method used in CellarWarden. The key with this is you will need to be able to have your system give a steady PV for a set output level on one of the actuators. It would be best to do this where the actuator is being tuned against ambient temperatures (e.g. if ambient is 20C, then put your setpoint to 30C for tuning the heating actuator and to 10C for the cooling actuator). If you are tuning the heating actuator, unplug or disable the cooling actuator, and vice versa for the cooling actuator tuning. This won't be perfect, but it should allow you to tune the system for dead time, etc.

iverberk commented 7 years ago

Ah, so what I didn't do was let the PID run until stable. I just used the hysteresis method to get to the setpoint and then activated the auto-tuning. I will try again after I let the PID routine run for a while until it gets stable. I started the AT at around 17:30 when the temperature starts increasing.

After that/while that is running I will take another look at the Cohen-Coon method and will use it to verify/adjust the findings. Thanks for getting back to me.

craigmw commented 7 years ago

Better yet, if you are going to do the Cohen-Coon tuning, tune the heating actuator against ambient temp. Disable the cooling actuator, and then set the output to about 30% and let the system settle on a PV that is stable (say 30-40C). Then increase the output to say 40% to introduce a disturbance. The output will eventually rise and then stabilize at a higher temperature (say 50C). Measure the dead time (dt), time to 63% of the change in PV (Tau) and the system gain (gp). Using these, you can calculate Kc, Ti and Td. To convert to PID gain values (which CellarWarden uses), Kp = Kc, Ki = Kp/Ti and Kd = Kp * Kc.

After you do this, you can tune the cooling actuator in a similar manner. It will be a bit slower because you need to account for the controller delay needed to prevent rapid cycling of the compressor (this is a compressor based cooler, right?). Do the same routine, tuning cooling against a return to ambient (with the heating actuator disabled). After you have calculated both your heating and cooling gains, plug these in independently for each actuator and try the system out with both actuators active and a setpoint in a desired range.

iverberk commented 7 years ago

Success! The auto-tuning completed overnight: http://pasteboard.co/9LrzfWwC.png . It got the following values: 18.708838, 0.005951079, 14704.0832 . These values give me stability to within 0.5 degrees of the setpoint. I reduced the D value just now to 50 to see what it does with the output. This is a really nice result though!

Going to try your latest recommendations next!

craigmw commented 7 years ago

Ivo:

It looks pretty good! Was this done on the heating actuator only?

iverberk commented 7 years ago

Yes, heater actuator only, cooling is done by returning to ambient temperature. I'm now doing the procedure with Cohen-Coon tuning. Let's see what that turns up :-)

craigmw commented 7 years ago

I would guess that the Z-N routine that is in CellarW will probably be a little more accurate, although it is a bit aggressive. I would suggest doing the same autotuning using cooling only, this time allowing the cooling actuator to function against ambient temperature. Again, a somewhat stable output at a setpoint below ambient (say 10C) should yield reasonable results if the output is moderate (again, with cooling output at around -20 to -80%).

craigmw commented 7 years ago

Ivo:

Where are you on this? I'd like to close the issue, but won't do so until you respond.

iverberk commented 7 years ago

Hi Craig, this issue can be closed. I've found parameters that work well enough for now and will keep fine-tuning. Thanks for all your guidance!

craigmw commented 7 years ago

Great to hear! Keep me posted on your progress.

Craig

craigmw commented 7 years ago

BTW, you may wish to do a git pull as I've fixed a few minor issues. These include resuming PID function after a reboot or power failure. Before, the PID would initialize and start back at zero output. For processes with long cycle times, this would require quite a bit of time for the PID to return to its appropriate output level after a shutdown. Now, the PID resumes where it left off with minimal disturbance. I also implemented a method to turn off all actuators after a reboot/power failure. This is important because after a reboot, the GPIO pins on the RPi are at an unknown state, so upon reboot, two issues were apparent. First, this could turn on an actuator even if it should be off, particularly when the GPIO line was buffered with a logic level shifter board. Another issue was that actuators associated with inactive GPIO pins would become activated and since the controller was not toggling their state, they would remain on. This new logic addresses these two issues.

iverberk commented 7 years ago

Hi Craig,

Very nice updates, I've upgraded!

I've done some more experiments. I've been able to get values from the auto-tuning for both heating and cooling. Using the actuators separately (either heating or cooling) results in quite a steady temperature. Depending on the ambient temperature the heating is automatically cooled down and vice-versa. However, when I activate the PID on one controller for both actuators it doesn't seem to work very well.

The big difference of course is the fact that instead of the ambient temperature being the 'counter-force', it is now the opposing actuator. As far as I can tell there are two problems with this approach:

  1. The actuators are still cooling or warming after being turned off. This requires the PID to compensate for that additional coolness/heat, but since we tune the actuators separately this is not taken into account.
  2. My cooling method is a freezer box. This actually cools the inside of the box really fast, much faster than the heating element. This results in a 'battle' that the heater can't win or only very slowly gets up to the required temperature. The nature of PID is that it cycles quite rapidly and this does not seem to work out really well with an 'unbalanced' cooler/heater power.

I still have doubts if the PID method is suitable for a compressor based actuator. The short intervals don't seem to match very well and a simple hysteresis yields pretty similar results. What is the reason that both actuators need to use the same algorithm?

Are you running a controller with both a heater and cooler activated? What are your experiences in terms of temperature stability given my previous remarks.

Another option is just to start tweaking the PID values to get a better match for a complete system (two actuators) but I haven't got the slightest idea how to systematically approach this. Will need to read up on some PID literature I guess.

craigmw commented 7 years ago

Ivo:

Sorry about the frustrations with this. I've really not used two-sided PID control much, so my experience is limited to theory. In my implementation, I have independent controllers for heating and cooling because I independently heat a fermenter to a setpoint considerably above the ambient temperature of the chamber, which is controlled by a separate controller. So, these are two independent loops. I usually use hysteresis control for the chamber and PID control for the fermenters. In this way, the heated fermenters can follow independent temperature profiles. I agree that getting good tuning parameters for compressor-based cooling is difficult. I think part of this difficulty is due to some noise in the input signal, which could be filtered by averaging or median filtering. I'm planning to introduce this in an update.

What temperature ranges are you interested in obtaining and what is the typical ambient temperature in which your "fermentation chamber" is surrounded? Does it necessarily need both heating and cooling? While CellarW doesn't explicitly support PID and hysteresis controlled actuators on the same controller, it is possible to do so without too much contention between actuators. So, you could have your cooling actuator controlled by a hysteresis controller and your heating actuator controlled by a PID controller. You would then need to set both to the desired temperature. If you wanted to run setpoint profiles, you could just load them from the same template and start them running simultaneously. It's not perfect, but it might get you what you want. Note that by this method, there will likely be times where both actuators are on and so they might be fighting a bit with each other. But if you can tweak their values appropriately, you could minimize this.

I need to set up a similar configuration to test this further. Thanks for all of your insight on this.

iverberk commented 7 years ago

Hi Craig,

There is no frustration at all, I rather enjoy these little experiments :-)

So my setup is just a freezer box (https://image.coolblue.io/products/302405) that contains two sensors, two fans and a heater tube. One sensor is mounted to the side-wall and the other is submerged in a glass of water to dampen the temperature variability. The water-submerged sensor accounts for 50% of the PV.

The temperature range that I'm looking for roughly falls between 2 and 30 degrees Celsius. After an initial fermentation step (25-28 degrees) the dough is usually retarded (1-4 degrees) for 1-2 days to draw out maximum flavour. After the retardation the temperature needs to be brought up to prepare for final baking. Ideally I would like to create temperature profiles for different kinds of bread. The typical ambient temperature is around 20-22 degrees but in the summer time it might increase to 25-30 degrees on very hot days, but this is the exception.

Your suggestion is indeed the only viable option if both actuators on one controller doesn't work out.

I think it could somehow be beneficial to only use the actuators if a large temperature difference needs to be overcome. For small temperature differences the system could just use one actuator and the ambient temperature to maintain temperature (this is actually what the auto-tuning measures). This means that within a configurable 'band' around the setpoint you would not immediately activate the opposing actuator and just let the ambient temperature take care as the opposing 'force'. This could maybe also compensate for the fact that the cooler brings the temperature down much faster than the heater can bring it up. I have to give this some more thought and work out some concrete use-cases, see if this makes any sense at all :-) For now, I'll probably experiment with your suggestion. Thanks again for the feedback.