Adding ON/OFF control & temp display to PID SCRIPT

Yikes! I can see where someone like me might be confused by that and do the wrong thing. (changing the OUTPUT but thinking I was changing the SETPOINT).

The algorithms I've seen have an OUTPUT that is read-only when the loop is AUTO and read-write when the loop is MANUAL.

  • Brian

Yes I kind of regret even bring up the subject of 'setpoint tracking' as I don't recall if it is even implemented in this existing library. It is however a very common mode of operation now a days with micro based PID controllers. In the old days of standalone analog PID controllers there was a separate manual output adjustment knob and a separate setpoint adjustment knob. It was up to the operator when switching from manual to automatic to first 'match up' the setpoint value to the existing output value so that the output would not spike when first placed back into automatic mode. Setpoint tracking did this step automatically and became a common operating feature.

Lefty

Yeah..., but I've been tinkering with it in "MANUAL" mode and it still sends an output signal to the heater. It doesn't seem to do any calculations in manual mode, but it still just keeps the output going.?

Is there a way I could just have the code start on "pause" or something until I depress the on button, then it goes to run mode while its depressed then pauses again if I release? Is there such a thing?

I can achieve what I want by wiring the PWM output from the arduino through the switch which is normally open so when I press the heat button it goes...

In response to what you guys are telling me...

How can I make it so that ONLY when I push the button the PID goes from MANUAL mode that has an output value of ZERO to AUTO and fully calculating.

I've been tinkering with it in "MANUAL" mode and it still sends an output signal to the heater. It doesn't seem to do any calculations in manual mode, but it still just keeps the output going.?

odd. as soon as it gets set to manual the pid should stop writing to the output variable. it won't make it 0, or anything really. if you want the output to go to 0 and stay there, use SetMode(MANUAL); followed by Output=0;

if you've done this and the pid is still changing the output, I'm going to have to take a look at the library source. it should not do that.

Brett

YES!! I tinkered with the code enough and finally got the "ON" button working just like I want.

Here's what I did.

/********************************************************
 * PID Simple Example
 * Reading analog input 0 to control analog PWM output 3
 ********************************************************/

#include <PID_Beta6.h>

//Define Variables we'll be connecting to
double Setpoint, Input, Output;

//Specify the links and initial tuning parameters
PID myPID(&Input, &Output, &Setpoint, 2,5,1);

const int ledPin =  13;
const int onPin = 1; // choose the input pin to trigger heater
const int upPin = 2;   // choose the input pin to increase temp
const int downPin = 4;   // choose the input pin to decrease temp
int buttonState = 0;     // variable for reading the pin status

void setup()
{
  //initialize the variables we're linked to
  Input = analogRead(0);
    Setpoint = 100;
    
  // Declare inputs
  pinMode(onPin, INPUT);    // declare pushbutton as input
  pinMode(upPin, INPUT);    // declare pushbutton as input
  pinMode(downPin, INPUT);    // declare pushbutton as input
  pinMode(ledPin, OUTPUT); 
  
  //turn the PID on
  myPID.SetMode(MANUAL);
  Output=0;
  myPID.SetSampleTime(250);
  myPID.SetTunings(2,3,1);
  myPID.SetOutputLimits(0, 220);
  
}

void loop()
{
   buttonState = digitalRead(onPin);

if (buttonState == HIGH) {     
    // turn LED/HEATER on:    
    digitalWrite(ledPin, HIGH);
     myPID.SetMode(AUTO);  
  } 
  else {
    // turn LED/HEATER off:
    digitalWrite(ledPin, LOW); 
     myPID.SetMode(MANUAL);
      Output=0;
  }
 
 Input = analogRead(0);
  myPID.Compute();
  analogWrite(3,Output);
 }

Now.. I can start toying with adding in those up/down temp lines of code.

Edit [timestamp=1246661743]...

Never mind. Looks like Jetski made progress while I was writing! Guess I'll have to respond faster or not at all!

Brett:

I assumed your algorithm provided writing to the OUTPUT with value clamping when in MANUAL mode. I suggested Jetski always send the output value (even when the loop was in manual) so the OUTPUT would be correctly restricted. When Jetski wrote this...

it still sends an output signal to the heater

...it's probably because of my suggestion.

When in MANUAL mode, is there a way to change the OUTPUT through your algorithm?

Jetski:

It would help if you posted the latest version of your Sketch.

Yeah..., but I've been tinkering with it in "MANUAL" mode and it still sends an output signal to the heater.

MANUAL mode just turns off the PID algorithm. It allows MANUAL control. Once in MANUAL mode it's up to you to change the OUTPUT.

Sorry for the confusion I've caused. I hope I haven't led you too far astray.

  • Brian

Thanks for at least starting to reply baldy. :slight_smile:

I've done a bit more now to try and get the buttons functioning. I added this to the end of the loop:

     myPID.SetMode(MANUAL);
      Output=0;
  }
 unsigned long lastTime;
if(digitalRead(upPin)==HIGH)
{
  if (lastTime+250<millis()) {
    Setpoint+=1;
    lastTime=millis();
  }
}

if(digitalRead(downPin)==HIGH)
{
  if (lastTime+250<millis()) {
    Setpoint-=1;
    lastTime=millis();
  }
}
 Input = analogRead(0);
  myPID.Compute();
  analogWrite(3,Output);
 }

Does that look like it will work?

Now, I don't have any way of knowing what the temp is currently set at if the code is working.

Is there a way for me to query the board for the current "Setpoint" while im tinkering with it up and down?
Im on a mac, I see the button on the arduino program for serial monitor. When I click it it gives me a baud rate option and a place to enter commands or code.

Is it some kind of "print" or "report" command?

Brian:

When in MANUAL mode, is there a way to change the OUTPUT through your algorithm?

currently there is not. when in manual, it's essentially as though the pid isn't there. you make a fair point about the output limits thought. I'm not sure what the answer is. I could throw in another function, but I think that would be confusing to most users.

Brett:

Some benefits if you add SetOutput (and an InternalSetOutput) to your algorithm...

  • Output clamping is handled consistently
  • If InternalSetOutput is virtual, the developer can add customized scaling, conditioning, and handling for the output (like drum-sequencing)
  • SetOutput can ignore the request if the loop is AUTO providing safety from accidental output changes

But... It's my understanding that your PID algorithm is rather new to the Arduino community. If you plan to continue working on it, you'll probably serve the community more if you wait for more feedback before making changes.

  • Brian

So is there any way for my to read the setpoint?

or how about putting something in the loop that constantly sends the value of the setpoint through the usb?

baldy

Ugh! Don't remind me! To make matters worse, what little is left needs to be cut. The hair in front is below my nose. I look like a damaged muppet. :o

Does that look like it will work?

You're close...

This...

 unsigned long lastTime;

...needs to be declared at the top of your Sketch (with Setpoint, Input, and Output) and needs to be initialized in setup...

void setup( void )
{
  // Existing stuff
  lastTime = millis();
}

Change this...

  if (lastTime+250<millis()) {

...to this...

  if (millis()-lastTime >= 250) {

...to avoid a problem when millis wraps back to zero.

So is there any way for my to read the setpoint?
or how about putting something in the loop that constantly sends the value of the setpoint through the usb?

In setup, prepare the serial port...

void setup( void )
{
  Serial.begin( 115200 );
  // Existing stuff
}

...then you can output whatever you'd like using something like this...

  Serial.print( "sp: " );
  Serial.print( Setpoint );
  Serial.println( "" );

You may have to use a different baud rate than 115200.

Good luck,
Brian