pythonscipyanalysisintegraldiode

Calculate the average power of a diode using voltage(time) data


I'm trying to calculate the average power of multiple diodes using recorded voltage(time) data, which isn't symmetrical. I wrote a script that uses the simpson function from the scipy.integral package to calculate the average voltage, which can be used to calculate the average power and also used it to calculate the average power directly by squaring the data and dividing it by the resistance and it seems to be working fine.
My problem is that if I use the integral of the average voltage to calculate the power the result is different than the one I'm getting from the simpson integral.
The result of the Source isn't that far off, but for the diodes it's always about half of the simpson integral.

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.signal import find_peaks
import openpyxl
import scipy.integrate as integral

file = "CSV8.csv"
data = pd.read_csv(file)

#Resistance
R = 1000
x = data["Second"]
#0.16 to move the data to the x-axis
y1 = (data["Volt1"]+0.16)**2/R
y2 = (data["Volt2"]+0.16)**2/R

yU1 = (data["Volt1"]+0.16)
yU2 = (data["Volt2"]+0.16)

#plt.plot(x, y1)
#plt.plot(x, y2)
plt.plot(x, yU1)
plt.plot(x, yU2)

peak = find_peaks(-y1, distance = 900)[0]

T = x[peak[3]]-x[peak[1]]

#plt.plot(x[peak], y1[peak], "x")
plt.plot(x[peak], yU1[peak], "x")

#Integral
xint = x[peak[1]:peak[3]]
y1int = y1[peak[1]:peak[3]]
y2int = y2[peak[1]:peak[3]]
yU1int = np.abs(yU1[peak[1]:peak[3]])
yU2int = np.abs(yU2[peak[1]:peak[3]])

int1 = integral.simpson(y1int, xint)
int2 = integral.simpson(y2int, xint)

intU1 = integral.simpson(yU1int, xint)
intU2 = integral.simpson(yU2int, xint)

print("P Source: ", int1/T, " P Diode: ", int2/T)
print("U Source: ", intU1/T, " U Diode: ", intU2/T)
print("P from U Source: ", (intU1/T)**2/1000, "P from U Diode: ", (intU2/T)**2/1000 )

plt.xlabel("Time t in s")
plt.ylabel("Voltage U in V")
plt.show()

The output is:

P Source: 0.020998072067580663 P Diode: 0.006863115468771637
U Source: 4.130740894612934 U Diode: 1.6910455615565707
P from U Source: 0.017063020338427666 P from U Diode: 0.0028596350912601775

with this dataset: https://pastebin.com/WtTdZVi5

Voltage(time)-diagram of the source (blue) and a diode (orange) I've tried reducing the noise, but the integral didn't change much.

hope the bold text made it a little more readable


Solution

  • This isn't a coding issue, your code is fine. The problem is the physics isn't quite right.

    The instantaneous power P, as you know, is V**2/R. You have then calculated the average power as the total energy (i.e. power integrated across a period) divided by the period. All good.

    However, if you want to calculate the average power from the 'average voltage' you have to take the RMS value (root-mean-square, i.e. do the integral of the square of the voltage and then square root everything at the end). Of course, as you'll do the v_{rms}**2, you'll just 'undo' the square root, and get the same integral again, basically.

    Let's see how this can work:

    def rms(y: np.array) -> float:
        return np.sqrt(np.mean(y**2))
    
    y1rms = rms(yU1int)
    y2rms = rms(yU2int)
    
    P1 = y1rms**2 / 1000
    P2 = y2rms**2 / 1000
    
    int1 = integral.simpson(y1int, xint) / T
    int2 = integral.simpson(y2int, xint) / T
    
    print(P1, int1)
    print(P2, int2)
    

    0.02099443290402991 0.020998072067580663

    0.006865154632322394 0.006863115468771637

    So, in summary, you can't just integrate the absolute value of the voltage and then expect to get back the correct average power, you need to take the rms average.