I write the PID controller of the buck converter to make the output voltage to follow the setpoint value I set in the code. In my code, the PID calculation is written in Timer interrupt while the setpoint is a square wave written in the loop part. Besides, the timer interrupt is used to calculate the PID every 1ms interval. However, after I download the code to the arduino uno and use the oscilloscope to observe the output voltage of the buck converter, the value of it is almost 0 at the beginning and after several seconds, the output voltage is much higher than the value of the setpoint I set. So, there may be something wrong with the code that I haven't noticed. Can anyone help me?
/working variables/
#include <PWM.h>
#define PIN_INPUT 5
#define PIN_OUTPUT 10
unsigned long lastTime;
//Unsigned long variables are extended size variables for number storage, and store 32 bits (4 bytes), while lastTime is stored variable
double Input, Output, Setpoint;
double ITerm, lastErr;
double error;
double Kp=1, Ki=0.2912,Kd=0;
int SampleTime = 1; //1 sec
volatile double i = 0;
int32_t frequency=100000;
void Compute();
void setup()
{
InitTimersSafe();
pinMode(PIN_OUTPUT, OUTPUT);
cli();//stop interrupts
//set timer0 interrupt at 2kHz
TCCR0A = 0;// set entire TCCR0A register to 0
TCCR0B = 0;// same for TCCR0B
TCNT0 = 0;//initialize counter value to 0
// set compare match register for 2khz increments
OCR0A = 249;// = (1610^6) / (100064) - 1 (must be <256)
// turn on CTC mode
TCCR0A |= (1 << WGM01);
// Set CS01 and CS00 bits for 64 prescaler
TCCR0B |= (1 << CS01) | (1 << CS00);
// enable timer compare interrupt
TIMSK0 |= (1 << OCIE0A);
sei();//allow interrupts
}
ISR(TIMER1_COMPA_vect){
Input = analogRead(PIN_INPUT);
Input = map(analogRead(PIN_INPUT), 0, 1023, 0, 255);
unsigned long now = micros();
//Returns the number of milliseconds passed since the Arduino board began running the current program
//int timeChange = (now - lastTime);
//if(timeChange>=SampleTime);
//the algorithm now decides for itself if it’s time to calculate. Also, because we now KNOW that it’s going to be the same time between samples, we don’t need to constantly multiply by time change
/Compute all the working error variables/
double error = 255*0.5 - Input;
ITerm += (Ki * error) ;
//x += y; // equivalent to the expression x = x + y;
double dErr = (error - lastErr);
/Compute PID Output/
Output = Kp * error + ITerm + Kd * dErr;
/Remember some variables for next time/
lastErr = error;
//lastTime = now;
analogWrite(PIN_OUTPUT, Output);
i++;
}
void loop()
{ for (int i=0;i<=500;i++){
Setpoint = 2550;
delay(1);
bool success = SetPinFrequencySafe(PIN_OUTPUT, frequency);
}
for (int i=0;i<=500;i++){
Setpoint = 2550.5;
delay(1);
bool success = SetPinFrequencySafe(PIN_OUTPUT, frequency);
}
}
withtimer.ino (2.28 KB)