Problem 4.8

Problem 4.8#

Fundamentals of Solar Cells and Photovoltaic Systems Engineering

Solutions Manual - Chapter 4

Problem 4.8

For a Silicon solar cell with short-circuit current I\(_{sc}\) = 10 A, saturation current I\(_0\)=2·10\(^{-9}\) A, and ideality factor n=1.2

a) Estimate the value of series resistance \(R_S\) that produces a reduction of the maximum power of 20% with respect to a cell with \(R_S\) = 0.

b) Do the same for the parallel resistance \(R_P\).

c) Redo both calculations for a similar cell but with half the \(I_L\), and compare the results.

First, we import the Python modules used, define one constant to set the I-V curve data size, and define the Boltzman constant.

import math
import numpy as np
import matplotlib.pyplot as plt

DATA_SIZE = 500
kB = 8.617333e-5  # eV·K-1

We define the variables for the I-V curve data

# These are values in the usual range for a typical 16.6 x 16.6 cm2 Si solar cell
IL = 10.0 # A
I0 = 2e-9 # A
n = 1.2

temperature = 25  #ºC
cell_area = 16.6*16.6 # cm2

Now we define a function to calculate the I-V curve of the solar cell. Note that we use a number of data points defined as the constant DATA_SIZE. The larger this number, the higher the precision, but also the longer computation time. Since the calculations are not very complex, you can use high numbers with almost instantaenous calculations in modern desktop computers or laptops.

def model_IV(IL, I0, n, Rs, Rp, temperature):
    # Thermal voltage
    kBT = kB*(temperature + 273.15)
    
    #I-V curve stored in a 2-column array: first column for voltages, second column for currents
    IVcurve = np.zeros((DATA_SIZE,2))
    
    # First, we calculate the I-V curve voltage range: from -0.1 V to Voc + 0.01 V
    # We want to have the I-V curve crossing the current and voltage axes to see the Isc and Voc
    # Voc without Rs/Rp.
    Voc0 = n*kBT*math.log(IL/I0)
    
    #Create the voltage list
    #Voltage range used: -0.1 to Voc+0.01
    IVcurve[:,0]= np.linspace(-0.1, Voc0+0.01, DATA_SIZE)
    
    #I-V curve without Rs effect
    IVcurve[:,1] = IL - I0*(np.exp(IVcurve[:,0]/(n*kBT))-1) - IVcurve[:,0]/Rp
    
    #Shift voltages to include Rs effect
    IVcurve[:,0] = IVcurve[:,0] - Rs*IVcurve[:,1]
    
    return IVcurve

We define another function to get the Pmax. Note that this function does not assume that the I-V curve is in the first quadrant.

Another two functions are used to calculate the Isc and Voc and detect the quadrant. Then, the function calculating Pmax moves the I-V curve to this quadrant, if it is not there yet.

# Obtains Isc by linear interpolation around V=0
def get_Isc(IVdata):
    """Returns the Isc of the input raw I-V curve"""

   # Sort data (interpolation function requires sorted data)
    IV_sorted = IVdata.copy()
    IV_sorted=IVdata[IVdata[:,0].argsort()] #Sort by voltages  
    
    Isc = np.interp(0,IV_sorted[:,0],IV_sorted[:,1])
    
    return Isc

# Obtains Voc by linear interpolation around I=0
def get_Voc(IVdata):
    """Returns the Voc of the input raw I-V curve"""

   # Sort data (interpolation function requires sorted data)
    IV_sorted = IVdata.copy()
    IV_sorted=IVdata[IVdata[:,1].argsort()]   #Sort by currents
    
    Voc = np.interp(0, IV_sorted[:,1],IV_sorted[:,0])
    
    return Voc

# Obtains the Pmax, and also the Vm and Im
def get_Pmax(IVdata):
  
   # Sort data and move to 1st quadrant
    IV_sorted = IVdata.copy()
 
    Isc = get_Isc(IV_sorted)
    if Isc<0:
        Isc*=-1
        IV_sorted[:,1]*=-1
    
    Voc = get_Voc(IV_sorted)
    if Voc<0:
        Voc*=-1
        IV_sorted[:,0]*=-1       
 
    IV_sorted=IV_sorted[IV_sorted[:,0].argsort()]   
   
 
    PV = IV_sorted.copy()
    PV[:,1] = IV_sorted[:,0]*IV_sorted[:,1]
    
    Pm = np.amax(PV[:,1])
    maxPosition = np.argmax(PV[:,1])
    Vm = PV[maxPosition,0]
    Im = IV_sorted[maxPosition,1]

    return Pm, Vm, Im

We make a graph of normalized Pmax vs Rs for the two solar cells (with Isc and Isc/2) and calculate the values of Rs that cause a 20% Pmax loss

# Two-column arrays for Pmax vs Rs
# Create the Rs list in the first colum
Rs_min = 0  # ohm
Rs_max = 0.2 # ohm
Pmax_vs_Rs = np.zeros((DATA_SIZE,2))
Pmax_vs_Rs[:,0] = np.linspace(Rs_min, Rs_max, DATA_SIZE)
Pmax_vs_Rs_halfIsc = np.zeros((DATA_SIZE,2))
Pmax_vs_Rs_halfIsc[:,0] = np.linspace(Rs_min, Rs_max, DATA_SIZE)

# Calculate the Pmax for the list of Rs
for x in range(DATA_SIZE):
    IV_curve = model_IV(IL, I0, n, Pmax_vs_Rs[x,0], 1e6, temperature) #Rp is assumed to be very large (1e6)
    Pm, Vm, Im = get_Pmax(IV_curve)
    Pmax_vs_Rs[x,1] = Pm

    IV_curve = model_IV(IL/2, I0/2, n, Pmax_vs_Rs_halfIsc[x,0], 1e6, temperature) #Rp is assumed to be very large (1e6)
    Pm, Vm, Im = get_Pmax(IV_curve)
    Pmax_vs_Rs_halfIsc[x,1] = Pm

# Normalize the Pmax: divide data by maximum value
Pmax_vs_Rs[:,1] =  Pmax_vs_Rs[:,1]/Pmax_vs_Rs[0,1]  
Pmax_vs_Rs_halfIsc[:,1] =  Pmax_vs_Rs_halfIsc[:,1]/Pmax_vs_Rs_halfIsc[0,1]  

# Plot the data
plt.plot(Pmax_vs_Rs[:,0], Pmax_vs_Rs[:,1], color='b', label='Isc')
plt.plot(Pmax_vs_Rs_halfIsc[:,0], Pmax_vs_Rs_halfIsc[:,1], color='r', label='Isc/2')
plt.xlabel('Rs (ohm)', size=14)
plt.ylabel('Pmax (W)', size=14)
plt.legend()
plt.show()

# Report the values
Pm_sorted=Pmax_vs_Rs[Pmax_vs_Rs[:,1].argsort()]
Rs_20loss = np.interp(0.8, Pm_sorted[:,1],Pm_sorted[:,0])
sResult = "Solar cell with IL="+ str(IL) + ": for an Rs="+ f"{Rs_20loss:.3}" + " \u03A9" 
sResult += " (" + f"{Rs_20loss*cell_area:.3}" + " \u03A9·cm2) " + "the Pmax loss is 20%"
print(sResult)

Pm_sorted=Pmax_vs_Rs_halfIsc[Pmax_vs_Rs_halfIsc[:,1].argsort()]
Rs_20loss = np.interp(0.8, Pm_sorted[:,1],Pm_sorted[:,0])
sResult = "Solar cell with IL="+ str(IL/2) + ": for an Rs="+f"{Rs_20loss:.3}"+ " \u03A9"
sResult += " (" + f"{Rs_20loss*cell_area:.3}" + " \u03A9·cm2) " + "the Pmax loss is 20%"
print(sResult)
    
../../_images/cd7a914c139c7c8ea7e80c695339e58fa947a4bbad27f99c569f00f0e1b91f24.png
Solar cell with IL=10.0: for an Rs=0.0128 Ω (3.54 Ω·cm2) the Pmax loss is 20%
Solar cell with IL=5.0: for an Rs=0.0257 Ω (7.08 Ω·cm2) the Pmax loss is 20%

As you can see, the Isc determines how the Rs affects the solar cell performance. For higher currents, the Rs creates a higher power loss.
IMPORTANT NOTE: the Rs is given also as a value per unit area since it is frequent to find it that way.

Now we do a similar analysis with Rp.

# Two-column arrays for Pmax vs Rs
# Create the Rp list in the first colum
Rp_min = 0.1 # ohm
Rp_max = 100 # ohm
Pmax_vs_Rp = np.zeros((DATA_SIZE,2))
Pmax_vs_Rp[:,0] = np.linspace(Rp_min, Rp_max, DATA_SIZE)
Pmax_vs_Rp_halfIsc = np.zeros((DATA_SIZE,2))
Pmax_vs_Rp_halfIsc[:,0] = np.linspace(Rp_min, Rp_max, DATA_SIZE)

# Calculate the Pmax for the list of Rp
for x in range(DATA_SIZE):
    IV_curve = model_IV(IL, I0, n, 0 , Pmax_vs_Rp[x,0], temperature ) #Rs is assumed to be very zero
    Pm, Vm, Im = get_Pmax(IV_curve)
    Pmax_vs_Rp[x,1] = Pm

    IV_curve = model_IV(IL/2, I0/2, n, 0, Pmax_vs_Rp_halfIsc[x,0], temperature) #Rs is assumed to be very zero
    Pm, Vm, Im = get_Pmax(IV_curve)
    Pmax_vs_Rp_halfIsc[x,1] = Pm

# Normalize: divide by max Pmax
Pmax_vs_Rp[:,1] =  Pmax_vs_Rp[:,1]/Pmax_vs_Rp[DATA_SIZE-1,1]  
Pmax_vs_Rp_halfIsc[:,1] =  Pmax_vs_Rp_halfIsc[:,1]/Pmax_vs_Rp_halfIsc[DATA_SIZE-1,1]  

# Plot the data
plt.plot(Pmax_vs_Rp[:,0], Pmax_vs_Rp[:,1], color='b', label='Isc')
plt.plot(Pmax_vs_Rp_halfIsc[:,0], Pmax_vs_Rp_halfIsc[:,1], color='r', label='Isc/2')
plt.xlabel('Rp (ohm)', size=14)
plt.ylabel('Pmax (W)', size=14)
# Use logarithmic scale for Rp axis to see data better
plt.xscale("log")
plt.legend()
plt.show()

# Report values
Pm_sorted=Pmax_vs_Rp[Pmax_vs_Rp[:,1].argsort()]
Rp_20loss = np.interp(0.8, Pm_sorted[:,1],Pm_sorted[:,0])
sResult = "Solar cell with IL="+ str(IL) + ": for an Rp="+f"{Rp_20loss:.3}"+ " \u03A9"
sResult += " (" + f"{Rp_20loss*cell_area:.3f}" + " \u03A9·cm2) " + "the Pmax loss is 20%"
print(sResult)

Pm_sorted=Pmax_vs_Rp_halfIsc[Pmax_vs_Rp_halfIsc[:,1].argsort()]
Rp_20loss = np.interp(0.8, Pm_sorted[:,1],Pm_sorted[:,0])
sResult = "Solar cell with IL="+ str(IL/2) + ": for an Rp="+f"{Rp_20loss:.3}" + " \u03A9"
sResult += " (" + f"{Rp_20loss*cell_area:.3f}" + " \u03A9·cm2) " + "the Pmax loss is 20%"
print(sResult)
    
../../_images/f19a008173f9378acab903903332c6f5159202cb9c8f68bd20e436a87225a753.png
Solar cell with IL=10.0: for an Rp=0.309 Ω (85.162 Ω·cm2) the Pmax loss is 20%
Solar cell with IL=5.0: for an Rp=0.626 Ω (172.380 Ω·cm2) the Pmax loss is 20%

As you can see, the Isc determines how the Rp affects the solar cell performance. For lower currents, a low Rp creates a higher power loss.
IMPORTANT NOTE: the Rp is given also as a value per unit area since it is frequent to find it that way.