Go Down

Topic: PID control humidifier - library example code does not work (Read 283 times) previous topic - next topic

gmarwaha

I'm trying to control a humidifier using a relay shield and a RH sensor (BME280). A simple on-off type control is not sufficient for my experiment and I want to use PID control. I used the example code provided on the  GitHub page but that doesn't work. I also tried out the variation that was suggested by another user (found here) with the same result.

I've attached my code - I've tried to print the output of myPID.Compute() function - it is always 0. If I try to implement a simple on-off control using if-else statements - that works as expected, so the problem is not the circuit/relay/humidifier/sensor.

Any help is appreciated.

gfvalvo

A simple on-off type control is not sufficient for my experiment and I want to use PID control.
Why? Isn't a humidifier either "on" or "off"? Seems like a Bang-Bang Controller with appropriate hysteresis is just the thing. Certainly works well for your house's HVAC system.

aarg

What makes you think the function returns the output value? Isn't there an output variable for that?
From the examples:
Code: [Select]
void loop()
{
  Input = analogRead(PIN_INPUT);
  myPID.Compute();
  analogWrite(PIN_OUTPUT, Output);
}

You didn't read the documentation and/or examples enough.
Look at the definition of the function. What type does it return?
Code: [Select]
bool PID::Compute()
  ... with a transistor and a large sum of money to spend ...
Please don't PM me with technical questions. Post them in the forum.

johnwasser

I used the example code provided on the  GitHub page but that doesn't work.
"doesn't work" in what way?
Send Bitcoin tips to: 1G2qoGwMRXx8az71DVP1E81jShxtbSh5Hp

gmarwaha

@gfvalvo
An on-off control would be fine for a house hvac (perhaps with a range instead of a single setpoint) but I'm  not using it for that purpose. I'm running an experiment to evaluate material properties in different conditions (incl. temperature, humidity, corrosive chemicals etc.) and would like to control it quickly and efficiently since the properties I'm investigating are also time dependant. An on-off control oscillates too much around the setpoint (for my equipment anyway) - which I'd like to avoid with PID control. 


@aarg
I know that the output of PID.Compute() would be a boolean and assigned to the variable Output as declared in the preamble. From what I understand, it is then being mapped on to a 0-5000ms (windowSize) range to implement a slow PWM. But the output is always zero which seems suspect. I've re-read the examples a couple of times but couldn't figure it out. Tried printing the calculated values at each step to see what's happening but that didn't get me far either.

@johnwasser
It does not work in the sense that the output (which I'm constantly monitoring) on the serial monitor does not change - regardless of where the input lies wrt the setpoint.

MarkT

Try logging the input, setpoint and output and posting it here?
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

gfvalvo

An on-off control oscillates too much around the setpoint (for my equipment anyway) - which I'd like to avoid with PID control.  
But that's how the PID RelayOutput  works anyway. Did you read the comments at the top of the code?

Quote
/********************************************************
 * PID RelayOutput Example
 * Same as basic example, except that this time, the output
 * is going to a digital pin which (we presume) is controlling
 * a relay.  the pid is designed to Output an analog value,
 * but the relay can only be On/Off.

 *
 *   to connect them together we use "time proportioning
 * control" it's essentially a really slow version of PWM.
 * first we decide on a window size (5000mS say.) we then
 * set the pid to adjust its output between 0 and that window
 * size.  lastly, we add some logic that translates the PID
 * output into "Relay On Time" with the remainder of the
 * window being "Relay Off Time"

 ********************************************************/

gmarwaha

I am familiar with how PIDs work - when the coefficients are properly selected, they should approximate the desired behaviour. The on-off control overshoots by a huge margin and isn't able to stabilize which is what I want to get rid of. Any form of PWM for controlling components that only have two states but we want a certain kind of output over a certain period of time. If the output does not change regardless of whethere input < setpoint or input > setpoint, isn't there something amiss? I've used both DIRECT and REVERSE to see if that makes a difference but it doesnt.

gmarwaha

Here's a screenshot of the serial monitor. The humidity value (input) changes goes both over and under the setpoint with no change in output.

johnwasser

@johnwasser
It does not work in the sense that the output (which I'm constantly monitoring) on the serial monitor does not change - regardless of where the input lies wrt the setpoint.
Were you also displaying Input and Setpoint so you could see that they were what you thought they were?

I assume you modified the example to use your humidity reading rather than the raw analog input.  Perhaps you made a mistake in that modification.  If you could show your modified example we might be able to help get it running.
Send Bitcoin tips to: 1G2qoGwMRXx8az71DVP1E81jShxtbSh5Hp

johnwasser

Here's a screenshot of the serial monitor. The humidity value (input) changes goes both over and under the setpoint with no change in output.
The PID "Output" is a float.  Why is it showing as an integer?
Send Bitcoin tips to: 1G2qoGwMRXx8az71DVP1E81jShxtbSh5Hp

gmarwaha

Not sure why it's always 0.
The Input is set to the corrected value of relative humidity in the code (Input = corrRH - Line 65)I printed values of both corrRH and Input in the serial monitor and they are the same.

aarg

You have no hysteresis in your on-off implementation. No wonder you think it "oscillates" more than you would like.
  ... with a transistor and a large sum of money to spend ...
Please don't PM me with technical questions. Post them in the forum.

gfvalvo

As I said in Reply #1, you have to include Hysteresis.
It's the resulting dead zone that prevents excessive "oscillations".
Code: [Select]
  if (corrRH < Setpoint - hysteresis)
  {
    digitalWrite(relay_pin, HIGH);
  }
  else if (corrRH > Setpoint + hysteresis)
  {
    digitalWrite(relay_pin, LOW);
  } else
  {
    // Dead Zone. Do Nothing!!!
  }

gmarwaha

Agreed. I did suggest the same (see reply #4 - using a range instead of a setpoint). However, why does the PID output not change - can you help me figure that out.

Go Up