PID Code for Arduino Uno to implement MPPT

I am trying to implement the P-and-O algorithm with Voltage reference control using the Arduino Uno.
But the code I have written for using the same is not giving proper results.

There are 2 parts of the code - the P&O algorithm to select Vref,
and then the PID part to generate the Duty Cycle using the Vref.

I have attached my code for reference.

Could you kindly help me out with a proper working code.

PnO_Vref_PID.pdf (36.3 KB)

Please read the sticky note on the first page this forum titled How to use this forum - please read

Then, post your source code correctly so that all may view it and most importantly, tell us what doesn't work correctly in your code.

I have attached my source code as a pdf along with my post.

The code is not giving the desired value of the duty cycle neither is the mppt(maximum power point tracking) algorithm being followed. Although the code has been developed based on the proper mppt algo.

So basically I do not get to understand what exactly is going wrong in the code. Maybe the PID part of the code is not right. And that is why I need help.

If I had deciphered what exactly was the problem, I would have mentioned it in my post.

Thank you.

Please post your code in the main body of the text using code tags.

After you you post your code, please tell us if this code was copied from an Internet source and if so, supply a link. It is possible your code was developed for different hardware and it will not run as-is on Arduino.

We also need to know how you are testing. What sensors, output devices, etc are being used and a schematic of how things are connected. Without duplicating your configuration, your results cannot be duplicated.

Code extracted from the PDF:

#include <TimerOne.h>
int v_in = A0, i_in = A3, pwm_pin = 9; // the input and output pins
int sampleRead = 50;
double Vpv, Ipv, Ppv, V_pv;
double Vpv_old, Ppv_old;
double dV, dP, err, P_PI, I_PI = 0.0;
double Vref, Vref_old = 10.0, del_V = 0.40;
double Vref_ul = 21.7, Vref_ll = 8;
double Kp = 0.138, Ki = 15.173;
int D = 512, D_old = 512;
double D_temp, D_temp_old = 0;
long timeDiff, prevTime = 0;
void setup() {
  pinMode( pwm_pin, OUTPUT );
  Timer1.initialize(20);
  Timer1.pwm(pwm_pin, D);
  Serial.begin(9600);
}
// ----- Reading the input signal at the corresponding analog pin
int read_Adc(int pinNo) {
  int sum = 0;
  int temp, i;
  for ( i = 0; i < sampleRead; i++) {
    temp = analogRead(pinNo);
    sum += temp;
    delayMicroseconds(20);
  }
  int avg = sum / sampleRead;
  return (avg);
}
// ----- Reading the inputs and converting them to their actual analog values
void readData() {
  Vpv = read_Adc(v_in) * 11.0 * (5.0 / 1023.0);
  Ipv = read_Adc(i_in) * (5.0 / 1023.0);
  Ppv = Vpv * Ipv;
}
// ----- The P and O - MPPT algorithm using Vref
void PnO() {
  dV = Vpv - Vpv_old;
  dP = Ppv - Ppv_old;
  if (dP > 0.0) {
    if (dV > 0.0) {
      Vref = Vref_old + del_V;
    }
    else {
      Vref = Vref_old - del_V;
    }
  }
  else {
    if (dV > 0.0) {
      Vref = Vref_old - del_V;
    }
    else {
      Vref = Vref_old + del_V;
    }
  }
  ranger();
}
// ----- To maintain Vref within a range
void ranger() {
  if ( (Vref > Vref_ul) || (Vref < Vref_ll)) {
    Vref = Vref_old;
  }
}
// ----- to generate PWM pulses using D
void pwmDuty() {

  err = Vpv - Vref;
  P_PI = Kp * err; // the Proportional term

  timeDiff = (millis() - prevTime) / 1000;
  I_PI += (Ki * err) * timeDiff; // the Integral term
  prevTime = millis();

  D_temp = P_PI + I_PI; // generated Duty cycle

  D = abs(D_temp * 1023); // converting to the PWM scale of 0 to 1023

  if (D > 900 || D < 100) {
    D = D_old;
  }
  Timer1.pwm(pwm_pin, D);
}
// ----- Displaying the data obtained
void printData()
{
  Serial.println("----------");

  Serial.println("V_pv = ");
  Serial.println(Vpv);

  Serial.print("I_pv = ");
  Serial.println(Ipv);
  Serial.print("Vref = ");
  Serial.println(Vref);
  Serial.print("Power = ");
  Serial.println(Ppv);

  Serial.print("D = ");
  Serial.println(D);
  Serial.print("Dtemp = ");
  Serial.println(D_temp);
}
// ----- Saving the data for the current iteration
void saveData() {
  D_old = D;
  D_temp_old = D_temp;
  Vpv_old = Vpv;
  Ppv_old = Ppv;
  Vref_old = Vref;
}
void loop() {
  readData();
  PnO();
  pwmDuty();
  printData();
  saveData();
  delay(250);
}

Part of the problem might be averaging 50 samples of the analog input. 50*1023 = 51,150 and an 'int' can only hold 32,767. This might cause an overflow into negative numbers. Change 'int sum = 0;' to 'unsigned long sum = 0;' or average no more than 32 samples. Since you are taking the trouble to average a bunch of samples you MIGHT want to round to the nearest integer rather than truncating:  int avg = (sum + sampleRead/2) / sampleRead; Since further calculations are done in float you might just want to return a float average rather than truncating or rounding to an integer.