About PID controller

Hi...
In PID controller code for relay output or generating a PWM for switching control ,
How to change the switching frequency ?

#include <PID_v1.h>
#define RelayPin 6

//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, DIRECT);

int WindowSize = 5000;
unsigned long windowStartTime;
void setup()
{
  windowStartTime = millis();

  //initialize the variables we're linked to
  Setpoint = 100;

  //tell the PID to range between 0 and the full window size
  myPID.SetOutputLimits(0, WindowSize);

  //turn the PID on
  myPID.SetMode(AUTOMATIC);
}

void loop()
{
  Input = analogRead(0);
  myPID.Compute();

  /************************************************
   * turn the output pin on/off based on pid output
   ************************************************/
  unsigned long now = millis();
  if(now - windowStartTime>WindowSize)
  { //time to shift the Relay Window
    windowStartTime += WindowSize;
  }
  if(Output > now - windowStartTime) digitalWrite(RelayPin,HIGH);
  else digitalWrite(RelayPin,LOW);

}

In the above code What is the use of window start time and now?

'WindowSize' is how many milliseconds per PWM cycle.

'windowStartTime' is the time the current PWM cycle started.

'now' is the current time (in milliseconds).

'now - WindowStartTime' is how far into the current PWM cycle we are.

The Output value is limited to the range 0 to WindowSize and sets the point in each PWM cycle where the output changes from HIGH to LOW:

  if(Output > now - windowStartTime) 
    digitalWrite(RelayPin,HIGH);
  else
    digitalWrite(RelayPin,LOW);

This might be easier to read as:

  if((now - windowStartTime) < Output) 
    digitalWrite(RelayPin,HIGH);
  else
    digitalWrite(RelayPin,LOW);

And that can be reduced to:

    digitalWrite(RelayPin,(now - windowStartTime) < Output);

K thank you :slight_smile:
But How to change the switching frequency in that code

How to change the switching frequency in that code

'WindowSize' is how many milliseconds per PWM cycle.

Sorry sir again disturbing you.
Actually I can't understand the logic of the part of the code which i have given below.
mainly this (now - windowStartTime>WindowSize) part.
Why we are using this?

Please explain me ....

unsigned long now = millis();
  if(now - windowStartTime>WindowSize)
  { //time to shift the Relay Window
    windowStartTime += WindowSize;
  }
  if(Output > now - windowStartTime) digitalWrite(RelayPin,HIGH);
  else digitalWrite(RelayPin,LOW);

ADI89:
Actually I can't understand the logic of the part of the code which i have given below.
mainly this:

unsigned long now = millis();

if(now - windowStartTime>WindowSize)
  { //time to shift the Relay Window
    windowStartTime += WindowSize;
  }

That's the part that starts a new cycle (windowStartTime += WindowSize;) when the old cycle is over (now-windowStartTime > WindowSize).

Hi...
in this code the output which is compaired with now-window startime , in which form that output will come?
Actually my doubt is , now and window starttime is in time but the output of PID is in other form (like it minimizes the error),
So how it'll be compaired with time?

if(Output > now - windowStartTime) 
    digitalWrite(RelayPin,HIGH);
  else
    digitalWrite(RelayPin,LOW);

Why are you using a floating-point variable in a time calculation?
Shouldn't the comparison be ">="?

AWOL:
Why are you using a floating-point variable in a time calculation?

I think it is because the output of the PID Library is a 'float'.

AWOL:
Shouldn't the comparison be ">="?

The '>' comparison is correct. If it was '>=' the relay would come on for 1 mS at the start of each 5-second interval even if Output was 0.

If I were writing it I would probably replace the entire if statement with this line:

    digitalWrite(RelayPin, now - windowStartTime < (unsigned long)Output);

Quote from: AWOL on 21-08-2013, 16:31:39
Why are you using a floating-point variable in a time calculation?
I think it is because the output of the PID Library is a 'float'.

Wouldn't it be better to round before comparing?

AWOL:

Quote from: AWOL on 21-08-2013, 16:31:39
Why are you using a floating-point variable in a time calculation?
I think it is because the output of the PID Library is a 'float'.

Wouldn't it be better to round before comparing?

I don't think that the extra half millisecond of accuracy is that important over the 5000 millisecond interval.

Hi...
sorry sir I can not get my answer.
how that code is generating a PWM signal?

ADI89:
Hi...
sorry sir I can not get my answer.
how that code is generating a PWM signal?

This line sets the duration, in milliseconds, of the PWM cycle to 5000:

int WindowSize = 5000;

This line tells the PID to use Output values between 0 and WindowSize (5000):

myPID.SetOutputLimits(0, WindowSize);

This part starts a new PWM cycle every WindowSize (5000) milliseconds:

  unsigned long now = millis();
  if(now - windowStartTime>WindowSize)
  { //time to shift the Relay Window
    windowStartTime += WindowSize;
  }

The expression (now - windowStartTime) calculates the number of milliseconds that have passed in the current PWM cycle. If that is less than the Output value the relay is turned ON. If that is greater than (or equal to) the Output value the relay is turned OFF.

  if(Output > (now - windowStartTime)) 
    digitalWrite(RelayPin,HIGH);
  else 
    digitalWrite(RelayPin,LOW);

If the PID calculates the need for full power, Output will be set to 5000. The relay will be ON for all 5000 milliseconds of each PWM cycle.

If the PID calculates the need for half-power, Output will be set to 2500. The relay will be ON for the first 2500 milliseconds (2.5 seconds) of each PWM cycle and OFF for the remaining 2500 milliseconds (2.5 seconds).

If the PID calculates the need for 1/5th power, Output will be set to 1000. The relay will be ON for the first 1000 milliseconds (1 second) of each PWM cycle and OFF for the remaining 4000 milliseconds (4 seconds).

thank you very much sir :slight_smile:

Hi...
I want a frequency of 6o KHz, so the time period will be 0.016 millisecond.

My question is ,How to change the Windowsize in Microsecond in this program?

ADI89:
I want a frequency of 6o KHz, so the time period will be 0.016 millisecond.
My question is ,How to change the Windowsize in Microsecond in this program?

I don't think there is any way to run the PID loop 60,000 times a second.

Perhaps you want to use a PWM output with a frequency of 60 kHz and use the PID loop to control the duty cycle.

That is a completely different sketch. First you need to program one of the timers to do 60 kHz PWM. From that you will determine the PWM range (maybe less than 0 to 255). You can then set the PWM limits as the Output limits on the PID and copy the PID Output directly to the PWM control register as quickly as you can run the PID loop.

But sir what will be the problem ? Is it due to calculation in PID function?

How to relate both the things , means how to copy PID output to the register?
What would be the changes in this code?

#include <PID_v1.h>
#define RelayPin 6

//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, DIRECT);

int WindowSize = 5000;
unsigned long windowStartTime;
void setup()
{
  windowStartTime = millis();

  //initialize the variables we're linked to
  Setpoint = 100;

  //tell the PID to range between 0 and the full window size
  myPID.SetOutputLimits(0, WindowSize);

  //turn the PID on
  myPID.SetMode(AUTOMATIC);
}

void loop()
{
  Input = analogRead(0);
  myPID.Compute();

  /************************************************
   * turn the output pin on/off based on pid output
   ************************************************/
  unsigned long now = millis();
  if(now - windowStartTime>WindowSize)
  { //time to shift the Relay Window
    windowStartTime += WindowSize;
  }
  if(Output > now - windowStartTime) digitalWrite(RelayPin,HIGH);
  else digitalWrite(RelayPin,LOW);

}

What is the maximum frequency up-to which PID loop work?

Hi johnwasser

I have understood the concepts you have explained regarding Windowsize and PWM. Can you please also describe the terms Kp, Ki and Kd in the same context. I do understand these terms for analog type output but dont understand for the relay type output.

Thanks a lot