PID controller for High Switching frequency

Hi…
I am attaching one code below, please tell me whether it’ll work or not for generating PWM signal for 6o KHz switching frequency.

#include "Arduino.h"

#include <PID_v1.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, DIRECT);

void setup()
{
  //initialize the variables we're linked to
  Input = analogRead(0);
  Setpoint = 100;
  TCCR0B = TCCR0B & 0b11111000 |0x01;

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

void loop()
{
  Input = analogRead(0);
  myPID.Compute();
  analogWrite(5,Output);
}

No, analogRead takes at least 100 usec, so you can't get faster than 10 kHz with your code. Plus, count how much times does it takes to calculate PID, you may insert microseconds() arduino function before and after PID line. Example:

  time_start = micros();
 PID(); 
  time_sampl  = micros() - time_start;

As analogRead() is waiting >80% of its time until AD conversion is done a lot of CPU cycles are lost. you can improve quite a bit on the analogRead() by making it asynchronous. Not trivial but not too complicated either.

See some previous work here - http://forum.arduino.cc/index.php?topic=157381.msg1178912#msg1178912 -

I don’t think the problem calls for the analogRead() and PID algorithm to be performed at 60KHz, only that the analog output runs at that frequency. I’m not familiar enough with the hardware timers to know whether you’re configuring them correctly to achieve that but if you haven’t already read it I suggest you read Nick Gammon’s tutorials about changing the analog output frequency.

Hi…
If we’ll use our own code for PID controller for generating PWM signal instead of using PID library, then it’ll work or not.
Code is given below

#include "Arduino.h"
double Setpt, Actual, Drive,Error,Integral,P,I,D,Last;

void setup(){
   TCCR0B = TCCR0B & 0b11111000 |0x01;
  //initialize the variables we're linked to
  Actual = analogRead(0);
  Setpt =20;
}

void loop(){
  Actual= analogRead(0);
   Setpt =20;
  Error = Setpt- Actual;
  if (abs(Error) < 0.1){ // prevent integral 'windup' 
    Integral = Integral + Error; // accumulate the error integral 
  } 
  else { 
    Integral=0; // zero it if out of bounds 
  } 
  P = Error*1; // calc proportional term kP=1
  I = Integral*4; // integral term kI=4
  D = (Last-Actual)*2; // derivative term kD=2
  Drive = P + I + D; // Total drive = P+I+D 
  Drive = Drive*250; // scale Drive to be in the range 0-255 
 
  if (abs(Drive)>255) { 
    Drive=255; 
  } 
  if (abs(Drive)<0){
    Drive=0;
  }
 Last=Actual;
  analogWrite(5,Drive);
}

Switching frequency is 62.5 KHz.

Hi…
If we’ll use our own code for PID controller for generating PWM signal instead of using PID library, then it’ll work or not.
Code is given below

#include "Arduino.h"
double Setpt, Actual, Drive,Error,Integral,P,I,D,Last;

void setup(){
   TCCR0B = TCCR0B & 0b11111000 |0x01;
  //initialize the variables we're linked to
  Actual = analogRead(0);
  Setpt =20;
}

void loop(){
  Actual= analogRead(0);
   Setpt =20;
  Error = Setpt- Actual;
  if (abs(Error) < 0.1){ // prevent integral 'windup' 
    Integral = Integral + Error; // accumulate the error integral 
  } 
  else { 
    Integral=0; // zero it if out of bounds 
  } 
  P = Error*1; // calc proportional term kP=1
  I = Integral*4; // integral term kI=4
  D = (Last-Actual)*2; // derivative term kD=2
  Drive = P + I + D; // Total drive = P+I+D 
  Drive = Drive*250; // scale Drive to be in the range 0-255 
 
  if (abs(Drive)>255) { 
    Drive=255; 
  } 
  if (abs(Drive)<0){
    Drive=0;
  }
 Last=Actual;
  analogWrite(5,Drive);
}

Switching frequency is 62.5 KHz.

If we'll use our own code for PID controller for generating PWM signal instead of using PID library, then it'll work or not

For what it's worth I agree, but do you have a question ?

//initialize the variables we're linked to
  Actual = analogRead(0);

Why bother? You're going to over-write it in a hundred microseconds or so.

ADI89:
it’ll work or not.

I can think of one way to find out.

I could n't get you PeterH

AWOL ,I could n't get you.

Why bother reading "Actual" in "setup()"? It'll get overwritten in "loop()".

K . Thank you :) So this code will work.

If you want to know whether it works, the most obvious way to find out is to test it.

I merged these two very similar threads.

may be a stupid question but I have one doubt in this code. analogRead(0) will give a value in 0-1024 ,but set point is a decimal value , how it’ll be possible?

#include "Arduino.h"

#include <PID_v1.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, DIRECT);

void setup()
{
  //initialize the variables we're linked to
  Input = analogRead(0);
  Setpoint = 100;
  TCCR0B = TCCR0B & 0b11111000 |0x01;

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

void loop()
{
  Input = analogRead(0);
  myPID.Compute();
  analogWrite(5,Output);
}

analogRead(0) will give a value in 0-1024

Close, but no cigar.

,but set point is a decimal value

The "int" returned by "analogRead()" will be promoted to a "double" in the assignment Input = analogRead(0);