Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add PID Control Hysteresis #398

Closed
kizniche opened this issue Feb 1, 2018 · 16 comments

Comments

@kizniche
Copy link
Owner

@kizniche kizniche commented Feb 1, 2018

From this comment

Proposed is the addition of the PID option band to enable PID hysteresis.

Example: Temperature Controllers Using Hysteresis

To my understanding it should operate like this:

If PID is set to Raise

Raise to the maximum value (setpoint + band value), then allow the condition to fall to the minimum value (setpoint - band value) before resuming regulation.

If PID is set to Lower

Lower to the minimum value (setpoint - band value), then allow the condition to raise to the maximum value (setpoint + band value) before resuming regulation.

If PID is set to Both

When the condition enters the band region (setpoint +/- band), do not apply the PID. When the condition falls outside (above or below), then begin applying the PID again. If it rises above the maximum value, begin lowering until it enters the band region. When it lowers below the minimum value, begin raising until it enters the band region.

Let me know your thoughts, if I'm missing a part of this concept, or if there are alternative methods that would be desirable to add.

kizniche added a commit that referenced this issue Feb 1, 2018
@kizniche

This comment has been minimized.

Copy link
Owner Author

@kizniche kizniche commented Feb 1, 2018

Currently untested, but I implemented the band option and the logic to determine the appropriate setpoint if raising/lowering:

if self.band:
band_min = self.setpoint - self.band
band_max = self.setpoint + self.band
if self.direction == 'raise':
setpoint = band_max
if current_value < band_max and self.below_band_min:
pass # Apply the PID
elif current_value < band_max and not self.below_band_min:
return 0
elif current_value > band_max:
self.below_band_min = False
return 0
elif self.direction == 'lower':
setpoint = band_min
if current_value > band_min and self.above_band_max:
pass # Apply the PID
elif current_value > band_min and not self.above_band_max:
return 0
elif current_value < band_min:
self.above_band_max = False
return 0
elif self.direction == 'both':
if current_value < band_min or current_value > band_max:
pass # Apply the PID
else:
return 0

I should get around to testing this weekend or sooner and have a release by the end of the weekend.

@zsole2

This comment has been minimized.

Copy link
Contributor

@zsole2 zsole2 commented Feb 2, 2018

I like this a lot, will be very useful for the health of my refrigerators!

@zsole2

This comment has been minimized.

Copy link
Contributor

@zsole2 zsole2 commented Feb 3, 2018

Kyle, looking at the link above on hysteresis control got me thinking that PID control and this hysteresis control are alternatives, and should not be combined together. A little googling seems to support this.
Do you agree?
In that case, this needs to be added as a separate function.
At brewing forums, there are plenty of discussions that they use PID for heating and hysteresis for cooling.

@kizniche

This comment has been minimized.

Copy link
Owner Author

@kizniche kizniche commented Feb 3, 2018

I added band to the PID options with the option of using it. If set to 0, there is no band and no hysteresis. However if you set it to a non-0 value, then it will operate like I describe in the first post, still using PID control. I don't think there needs to be a separation, but being able to turn it off is essential.

@kizniche

This comment has been minimized.

Copy link
Owner Author

@kizniche kizniche commented Feb 3, 2018

I can't conceptualize how the same PID can use hysteresis for just lowering and not use it for raising.

I can see two PIDs being used, one raising, and one lowering with hysteresis. This could work well, without the PIDs not competing too much if tuned properly.

@zsole2

This comment has been minimized.

Copy link
Contributor

@zsole2 zsole2 commented Feb 3, 2018

I believe that those were two different operations, but I'm not familiar with brewing. The competition was a main topic of the discussion, though.

1 similar comment
@zsole2

This comment has been minimized.

Copy link
Contributor

@zsole2 zsole2 commented Feb 3, 2018

I believe that those were two different operations, but I'm not familiar with brewing. The competition was a main topic of the discussion, though.

@kizniche

This comment has been minimized.

Copy link
Owner Author

@kizniche kizniche commented Feb 3, 2018

The current iteration of Hysteresis in Mycodo's PID controllers can theoretically work very well together. Here's one heating/cooling scenario:

PID 1: Heat, Raise to 30 °C

Setpoint: 30 °C, Hysteresis: 0 (disabled), the PID will raise the temperature to 30 °C and stop when the temperature is above 30 °C.

PID 2: Cool, Lower to 31 °C

Setpoint: 33 °C, Hysteresis: 2 (Min Band: 31 °C, Max Band: 35 °C), the PID will lower to 31 °C, then stop until the temperature rises above 35 °C, at which point it will begin regulating again to 31 °C.

Leaving the gap of one degree (30 °C to 31 °C, there shouldn't be any direct competition between the PID controllers. You would even make the gap 0 °C (Rise to 30 °C, Lower to 30 °C) and the PIDs should still function properly (considering they're well-tuned).

@kizniche

This comment has been minimized.

Copy link
Owner Author

@kizniche kizniche commented Feb 3, 2018

I just tested on a PID set to Raise (so should also work for Lower). Looks good. Next to test Both directions.

screenshot-192 168 0 10-2018-02-03-13-34-40

@kizniche

This comment has been minimized.

Copy link
Owner Author

@kizniche kizniche commented Feb 3, 2018

With testing the PID with direction set to Both, I had to fix some issues related to the wrong outputs being activated, due to the integrator and/or derivator. To do this, I reset both the integrator and derivator upon the current measurement reaching the opposite band threshold. That is, when the measurement reaches beyond either the Minimum Band or Maximum Band, the integrator and derivator are reset to 0, so the PID acts as though it were just turned on. This creates a smooth output instead of the aberrant behavior seen in the first graph, below.

Before Fix

screenshot-192 168 0 10-2018-02-03-15-17-59

After Fix

screenshot-192 168 0 10-2018-02-03-16-57-28

kizniche added a commit that referenced this issue Feb 3, 2018
@kizniche

This comment has been minimized.

Copy link
Owner Author

@kizniche kizniche commented Feb 3, 2018

Another test but with less steep slopes so the PID deactivation is more obvious when the measurements enter between the bands.

screenshot-192 168 0 10-2018-02-03-17-52-14

@zsole2

This comment has been minimized.

Copy link
Contributor

@zsole2 zsole2 commented Feb 5, 2018

I have a few test examples now.
First, the nice one:
image

This is my refrigerator PID, which was on 300s periods. It is clear that the frequency of operation is decreased.
Now the less nice one:
image

This is my processor fan, on 60s period. Need some tuning.
Interestingly, without the band it looked quite OK (not the same system, but the current system looked quite similar):
image

About 5-15s run of the fun kept the the processor at 40C. Now it is much worse. I'll remove the band to check that indeed the fan behaved similarly in the current system.

@zsole2

This comment has been minimized.

Copy link
Contributor

@zsole2 zsole2 commented Feb 5, 2018

Here is the CPU fan with the previous PID settings, without the band:
image

@frodus17

This comment has been minimized.

Copy link

@frodus17 frodus17 commented Feb 12, 2018

Kyle,
When I get time this week, I'll play around with this to test.

@kizniche

This comment has been minimized.

Copy link
Owner Author

@kizniche kizniche commented Mar 4, 2018

Let me know if there are any issues. I'm closing this, as I believe it's complete.

@kizniche kizniche closed this Mar 4, 2018
@frodus17

This comment has been minimized.

Copy link

@frodus17 frodus17 commented Mar 4, 2018

Sounds good, looks OK on my end for all of the delays and hysteresis.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants
You can’t perform that action at this time.