Using MOSFET and Arduino for PV IV curve tracer.

Thread Starter

JohanEricson

Joined Aug 30, 2017
32
I've been thinking of making a quick and dirty IV-curve tracer for solar panels, and I finally got the time.
It consists of an IRF520 MOSFET to function as a VCR, an INA260 breakout board to take the measurements and an Arduino to generate a PWM and gather the data onto an SD card.

Everything is working as it should, the data is neatly collected and there's no magic smoke. Success!

Or so I thought until I started to look at the data and plotting the actual IV curve...
It looks awfully linear and not at all how I expected, and I can't for the life of me figure out why.

I've been doing some reading on MOSFET and logic level PWM and I've come to the conclusion that the IRF520 is not the best match for the Arduino. But I've measured currents up to around 3A, which seems to be about what I can expect from the IRF520 with Vgs at 5V.

I have also included a reference PV cell to calculate the irradiance in w/m2.

The graph is based on these circumstances:
* Panel data: Voc = 21.5, Isc = 3.92, Vmp = 17.3, Imp = 3.56, Pmp = 60W
* about 800w/m2 irradiance 90 degrees to the panel. Not all over the panel tough, this might explain the low Isc.
* Vgs is a 980Hz PWM, that is stepping duty cycle from 0 to 255 bits 1 bit at a time.
* The light source is a bunch of 250W lights.
IV curve.png



So Voc seems to be as stated by the panel datasheet.
Isc is low, but I've confirmed with a multimeter that with the setup I used it actually was about 1.6 A.

So now, let's get to my qeustion: Why is the current decreasing linearly ? I have a hard time telling if it's related to the MOSFET and/or the INA260 or the fact that i don't have the full 1000w/m2 irradiance or something else...

Any thoughts on this would be really helpful!
I guess my knowledge is lacking, and I don't even know I don't know. So I hope to learn something new!

Thank you for reading!
 

AlbertHall

Joined Jun 4, 2014
11,500
My guess for what it's worth:
(For a better guess, give us a full schematic.)
If you are using the PWM to turn the MOSFET on and off then the panel won't see other than maximum or minimum current, it won't ever be seeing a current in between them.
Now the PWM is just changing the proportion of time you're getting maximum current so I would expect the average of that to be linear with the PWM.

I think you're going to need a load resistance which you can vary smoothly over a range. A MOSFET could do that if you feed the gate with a smoothly changing voltage but it's going to generate a lot more heat and need a big heatsink.
 

Irving

Joined Jan 30, 2016
2,065
You're not really loading the PV panel with that setup as previously stated. You need an electronic load. For under 200W look at the cheap e-loads available on eBay /Amazon/AliExpress eg https://m.aliexpress.com/item/1005001413586633.html as a basis or roll your own, search YouTube for "e-load", there are plenty of examples.

A better device for this purpose are the Linear L2 range of MOSFETs from LittelFuse/IXYS, eg the IXTH64N10L2 that will, on the right heatsink, dump 200W for under $5.
 

Thread Starter

JohanEricson

Joined Aug 30, 2017
32
My guess for what it's worth:
(For a better guess, give us a full schematic.)
If you are using the PWM to turn the MOSFET on and off then the panel won't see other than maximum or minimum current, it won't ever be seeing a current in between them.
Now the PWM is just changing the proportion of time you're getting maximum current so I would expect the average of that to be linear with the PWM.

I think you're going to need a load resistance which you can vary smoothly over a range. A MOSFET could do that if you feed the gate with a smoothly changing voltage but it's going to generate a lot more heat and need a big heatsink.
Ah, seems to make sense!
I've read this paper that uses an LP filter on the gate, and it looks like they are getting pretty good results. So I guess I'll try that to start with. In the video I linked below an LP filter is used on the PWM together with a TC4420 MOSFET driver. What is the purpose of the driver, can I use say a voltage OP-amp voltage follower or something instead?

You're not really loading the PV panel with that setup as previously stated. You need an electronic load. For under 200W look at the cheap e-loads available on eBay /Amazon/AliExpress eg https://m.aliexpress.com/item/1005001413586633.html as a basis or roll your own, search YouTube for "e-load", there are plenty of examples.

A better device for this purpose are the Linear L2 range of MOSFETs from LittelFuse/IXYS, eg the IXTH64N10L2 that will, on the right heatsink, dump 200W for under $5.
Thank you! I watched this video and it's given me some enlightenment. It's a bit more evolved than what I have the need for at the moment but I can use it as a guide. I'm wondering what's the purpose of the TC4420 MOSFET driver before the RC-filter?

I also found this video that have a lot of really useful information! I'll leave it here is anyone wanting to build one is ending up on this thread.
 

Irving

Joined Jan 30, 2016
2,065
I like this video, he's using a proper Linear MOSFET, the right device for the job... the others are using standard MOSFETs which have a very small ohmic region.

GreatScott's design is OK but his explanation is back to front... the saturation region is where you are when switching for minimal losses...

I'm wondering what's the purpose of the TC4420 MOSFET driver before the RC-filter?
His use of PWM with the driver is to get enough drive power after the losses in the LPF. The design is flawed IMHO because of the PWM which generates quantization noise in the load.

The ElectroNoobs version is a better explanation and design, with analog op-amp feedback & control, though his 1ohm current sense resistor is too large and limits his lowest working voltage (though there are ways round that).

I use a proper 14bit DAC driving a high-power op-amp in my 1500W e-load, and a 14bit ADC to measure both voltage and current, with a 100A 75mV shunt for current sensing.
 

Thread Starter

JohanEricson

Joined Aug 30, 2017
32
Ha!
At least now it looks correct!
I changed the IRF520 to one with more compatible characteristics and added a simple RC filter on Vgs.
Still quick and dirty but seems to do the job. I will have to look into the values of R and C in the filter to be able to decrease the sampling frequency and still get correct readings. egen iv.jpg

And I will definitely more proper one with a DAC in the future.
 

Thread Starter

JohanEricson

Joined Aug 30, 2017
32
So i think i have it working about as well as i need it to at the moment, i have written a python program to take the data from the serial port to plot and do some analysis on.
And since I do not really know how precise the measurements are i decided to also to do 3 rounds of measuring, i.e make 3 IV curves to see if they differ and make a mean curve. But i get some weird results in curve no. 2 and 3...

The duty cycle for the MOSFET gate is starting at 130 and stepping up 1 bit at a time till it reaches 255. (i have not yet looked more into what range is actually required), making the voltage start av Voc and current at 0 A. And the first time it's working very well! But the second and third time the first 3 or 4 values gives a current at about Isc (about same as the last values in the previous measuring round)

I have tried to see if it's the python code that's behaving strangely, but the data looks to be wrong directly from the Arduino.
I've tried to add a long delay between the 3 measuring rounds but no luck...

Adding some pictures and the Arduino code in hopes that someone can spot some mistake that i do not know is a mistake.
Arduino Main:
#include <Adafruit_INA260.h> // Bibliotek för ina260

Adafruit_INA260 ina260 = Adafruit_INA260();

//Variabler för ina260
int sampleTime = 10;
float current;
float voltage;
float power;

// Variabler för referenscell
int refCellPin = A1;
float refCellVoltage = 0;


// Variabler för IV-tracer
int PWMPin = 6;
int dutyCycle = 130;
int dutyStep = 1;
int i = 0;

void setup() {
  Serial.begin(115200);
  while (!Serial) { delay(10); } // Wait until serial port is opened
  ina260Setup();
  refCellSetUp();
  IVSetUp();
}

void loop() {
  while(i<3){
    Serial.println("Current,Voltage,Power,dutyCycle,Irradiance");
    IV();
    i++;
    dutyCycle=130;
    delay(5000);
  }
}
IV Function:
void IV(){
  dutyCycle = 130;
  while(dutyCycle <= 255){
      analogWrite(PWMPin, dutyCycle);
    getElectric();
    refCell();
    printSerial();
      dutyCycle = dutyCycle+dutyStep;
    delay(sampleTime);
  }
}
serial print function:
void printSerial(){
  Serial.print(current);
  Serial.print(",");

  Serial.print(voltage);
  Serial.print(",");

  Serial.print(power);
  Serial.print(",");

  Serial.print(dutyCycle);
  Serial.print(",");
 
  Serial.println(refCellVoltage * 12.8535, 4);
 
}
Measuring 1

CurrentVoltagePowerdutyCycle
0​
19832.5080.00
130​
0​
19835.0080.00
131​
0​
19835.0050.00
132​
7.5019827.50150.00
133​
51.2519802.501010.00
134​
103.7519763.752050.00
135​
153.7519731.253030.00
136​
216.2519693.754260.00
137​


Measuring 2
CurrentVoltagePowerdutyCycle
3737.5055.00200.00
130​
3738.7565.00240.00
131​
3378.7512258.7553990.00
132​
992.5019212.5019070.00
133​
420.0019535.008220.00
134​
333.7519606.256540.00
135​
338.7519602.506640.00
136​

Measuring 3
CurrentVoltagePowerdutyCycle
3737.5055.00200.00
130​
3738.7565.00240.00
131​
3390.0012978.7555260.00
132​
996.2519195.0019120.00
133​
500.0019500.009750.00
134​
396.2519566.257760.00
135​
378.7519576.257410.00
136​
 

Irving

Joined Jan 30, 2016
2,065
Need to see the code for the other subroutines. Are you artificially rounding the numbers? Zero current shouldn't produce a non-zero power?

There's also something odd about your current in runs 2 and 3 in that increasing duty cycle should increase current but it seems to be going down, which suggests this isn't working the way you think it is...

Have you verified the ina260 readings with a multimeter, both V and I?
 

Thread Starter

JohanEricson

Joined Aug 30, 2017
32
Need to see the code for the other subroutines. Are you artificially rounding the numbers? Zero current shouldn't produce a non-zero power?

There's also something odd about your current in runs 2 and 3 in that increasing duty cycle should increase current but it seems to be going down, which suggests this isn't working the way you think it is...

Have you verified the ina260 readings with a multimeter, both V and I?
The zero values for the current were changed manually in excel, they are actually negative coming from the INA260. The values are all in mili-whatever.
CurrentVoltagePowerdutyCycle
-3,75​
19832,5​
80​
130​
-3,75​
19835​
80​
131​
-2,5​
19835​
50​
132​
7,5​
19827,5​
150​
133​
51,25​
19802,5​
1010​
134​
103,75​
19763,8​
2050​
135​

So the power seems to be |current| * voltage and rounded up directly from the INA260.

Yeah, those strange values in run 2 and 3 are what is confusing me, they are starting high for a couple of points in the beginning, then dropping down to values that i expect them to and follow the expected values til the end.

Reference PV cell:
void refCell(){
  refCellVoltage = analogRead(refCellPin)*(1.1/1023)*1000;
}
Get electric values:
void getElectric(){
  current = ina260.readCurrent();
  voltage = ina260.readBusVoltage();
  power = ina260.readPower();
}
The thing that is confusing me is that it seems to be working very well for the first run and then not so well for the second and third run...

I guess I would have to measure with a multimeter to figure out if the strange values are the actual values or something lagging in the serial communication. Not really sure at the moment how to write a code that would "simulate" the same conditions but slow enough to be able to measure with a multimeter?

Attaching a picture of the plots also, might make it easier to know what I mean about the data being strange.
Figure_1.png

Thank you so much Irving!
 

Irving

Joined Jan 30, 2016
2,065
Add this at the top of the loop...


C:
While(!Serial.available()){ };
char ch = Serial.read();
This will stall the loop and progress it each time you send a key press to the Arduino from the serial monitor.

Or you could do it with a push button wired to ground from a GPIO pin... If you prefer I could post the code for that..
 
Top