Go Down

### Topic: Programming help needed for solar maximum power point tracker MPPT (Read 1 time)previous topic - next topic

#### antman85

##### Feb 01, 2016, 11:26 am
Hey guys

I've built a buck converter board designed to charge batteries from a higher voltage solar panel see below thread
https://forum.arduino.cc/index.php?topic=374608.0

I've got some code running at the moment which works well at above 50 watts but once the power drops it finds a false maximum power point and gets stuck there until reset. The code works on dropping output current instead of output power.

This board has a huge amount of potential as a solar charger but needs a decent programmer to get it working properly. I'm very much a hardware guy and even Arduino is difficult for me to program.

I'd be willing to exchange a complete board for somebody's time and effort to write some code.

Here is the current code I'm using
Code: [Select]
`// ------------------------------------------------------------------------// ------------------------------------------------------------------------//// Boost Maximum Power Point Tracking// Using Arduino Uno// by: Rusdy Simano// Last Update: 10 June 2014// // Full details in:// http://epxhilon.blogspot.com.au///// ------------------------------------------------------------------------// ------------------------------------------------------------------------// ------------------------------------------------------------------------// I/O pin settings// ------------------------------------------------------------------------const int pin_Vin = 0;          // pin of Vin connected to (A0)const int pin_Iin = 3;          // pin of Iin connected to (A3)const int pin_Vout = 2;         // pin of Vout connected to (A2)const int pin_Iout = 1;         // pin of Iout connected to (A1)const int switchPin = 11;  // pin of switching output connected to MOSFET// ------------------------------------------------------------------------// Constant variables//// RAW units are readings from Arduino Analogues// Refer to the schematic for engineering unit conversion//// ------------------------------------------------------------------------const int Vin_min = 230;  // Variable to store Vin_min, this is RAW unit (0 - 1023)        // Currently, '430' corresponds to around 12VDCconst int Iin_max = 1000; // Variable to store Iin_max, this is RAW unit (0 - 1023)const int Iout_max = 120; // Variable to store Iout_max, this is RAW unit (0 - 1023)                                // With current PCB (Resistor drawn PCB), 800 (RAW) equals to 3 Amperes  const int avgNum = 8;   // Number of iterations of the adc routine to average the adc readings// ------------------------------------------------------------------------// Variable declarations//// RAW units are readings from Arduino Analogues// Refer to the schematic for engineering unit conversion//// ------------------------------------------------------------------------int Vin = 0;    // Variable to store Input Voltage, this is RAW unit (0 - 1023)int Iin = 0;    // Variable to store Input Current, this is RAW unit (0 - 1023)int Vout = 0;   // Variable to store Output Voltage, this is RAW unit (0 - 1023)int Iout = 0;   // Variable to store Output Current, this is RAW unit (0 - 1023)int Vout_max = 258; // Variable to store maximum output voltage, this is RAW unit (0 - 1023)      // With current schematic, '830' corresponds to 42V output voltage max.int Vout_trickle = 254; // Variable to store trickle voltage charge, this is RAW unit (0 - 1023)      // With current schematic, '826' corresponds to 41.8V output voltage max.int currentPrev = 0;  // Variable to store Previous Sampled Current, this is RAW unit (0 - 1023)int currentDiff = 0;  // Variable to store Current Difference, this is unitlessint dutyCycle = 0;  // Variable to store duty cycle of PWM output to MOSFET, 0 to 255int state = 0;    // variable to store state machine      // State '0' is start-up// ------------------------------------------------------------------------// This routine is automatically called at powerup/reset// ------------------------------------------------------------------------void setup(){//  Serial.begin(9600);// running with high speed clock (set prescale to 16)// so that analog sampling time is now approximately 17microsecond// Source: Arduino Cookbook by MichaelMargolis 2nd chapter recipe 18-9  bitClear(ADCSRA,ADPS0) ;  bitClear(ADCSRA,ADPS1) ;  bitSet(ADCSRA,ADPS2) ;// Set switchPin to output mode  pinMode(switchPin, OUTPUT);   // Increase PWM frequency to 31kHz// Source: http://playground.arduino.cc/Code/PwmFrequency  TCCR2B = TCCR2B & 0b11111000 | 0x01;}// ------------------------------------------------------------------------// This routine selects maximum output voltage during start-up// specifically for Rusdy's shed setup//// If 24VDC battery is connected, this is a lead acid battery// else, assume e-Bike battery, 36V Lithium NMC//// With current schematic:// '356' corresponds to around 18.0 VDC output voltage// '553' corresponds to around 28.0 VDC output voltage// '557' corresponds to around 28.2 VDC output voltage// '561' corresponds to around 28.4 VDC output voltage// '830' corresponds to around 42.0 VDC output voltage//  // ------------------------------------------------------------------------void determine_Vout_Max(void){    if ((Vout >= 356) && (Vout <= 561)) // If Lead Acid 24VDC battery detected  {    Vout_max = 561;    Vout_trickle = 557;  }}// ------------------------------------------------------------------------// This routine reads and averages the analog inputs for this system//// It is called with the ADC channel number (pin number) and returns the average ADC// value as an integer. //// Credit: http://www.timnolan.com/uploads/Arduino%20Solar/ppt.pde// ------------------------------------------------------------------------int read_adc(int channel){  int sum = 0;  int temp;  int i;    for (i=0; i<avgNum; i++)  {                             // loop through reading raw adc values avgNum number of times      temp = analogRead(channel); // read the input pin      sum += temp;                // store sum for averaging    delayMicroseconds(10);      // pauses for 10 microseconds    }  return(sum / avgNum);         // divide sum by AVG_NUM to get average and return it}// ------------------------------------------------------------------------// Main routine// ------------------------------------------------------------------------void loop(){   Vout = read_adc(pin_Vout);   // Read Output Voltage    Vin = read_adc(pin_Vin);   // Read Input Voltage  Iout = read_adc(pin_Iout);     // Read Output Current  if ((Vin >= Vin_min) && (state == 0))   // Select maximum output voltage        // Only required at start-up  {    determine_Vout_Max();    state = 1;      // Change state  }  currentDiff = Iout - currentPrev;  // Calculate the current difference between now and previous sample  if ((Vout >= Vout_max) || (Vin <= Vin_min))  {    dutyCycle = 0;    // If input and output voltages outside limit,        // reset dutyCycle to 0 (of 255), i.e. OFF  }  else if (Vout >= Vout_trickle)  {    dutyCycle = dutyCycle - 8;  // If output voltage at trickle threshold        // reduce dutyCycle  }  else if ((currentDiff < 0) || (Iout > Iout_max))  {    dutyCycle = dutyCycle - 4;  // If output current is decreasing, OR beyond maximum        // reduce dutyCycle  }  else  {    dutyCycle = dutyCycle;  // else, do nothing  }    if (dutyCycle < 1)  {    dutyCycle = 0;   // making sure dutyCycle is not negative  }  else if (dutyCycle > 200)  {    dutyCycle = 200;    // making sure dutyCycle does not exceed 200 per 255  }  analogWrite(switchPin, dutyCycle);  delay(100);      Vout = read_adc(pin_Vout);   // Read Output Voltage    Vin = read_adc(pin_Vin);   // Read Input Voltage  Iout = read_adc(pin_Iout);     // Read Output Current    currentPrev = Iout;  dutyCycle = dutyCycle + 1;  if ((Vout >= Vout_max) || (Vin <= Vin_min))  {    dutyCycle = 0;    // If input and output voltages outside limit,        // reset dutyCycle to 0 (of 255), i.e. OFF  }  else  {    dutyCycle = dutyCycle;  // else, do nothing  }  analogWrite(switchPin, dutyCycle);  delay(10);   }`

#### backwoodsjack

#1
##### Nov 03, 2016, 07:43 pm
I'm interested.. If u still are there and still in need of help.. never-the-less i wonder if u got it figured out by now..

#### allanhurst

#2
##### Nov 06, 2016, 01:55 am
All you do is continuously vary the pwm up and down a bit (5%?) and find which way gives you the highest output current - follow that ..

regards

Allan

#### PaulMurrayCbr

#3
##### Nov 18, 2016, 04:46 am
If setting the duty cycle cant hurt anything, then you could just do a sweep every minute or so.

Alternatively, you could write code whose job it is to start trying to track the appropriate setting when it senses a  change.

How ab out: can you attempt to describe in english what value switchPin should be set to, given the values of Vout, Vin, and Iout?
http://paulmurraycbr.github.io/ArduinoTheOOWay.html

Go Up