-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 4f0d8e5
Showing
9 changed files
with
206 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# PWM Signal Simulation & Characterization Project | ||
Thank you for checking out this project! Although, this project doesn't haven't any special use other than to showcase my skills, feel free to clone this repo and play around with it for whatever reason you may have! | ||
## Things You Should Know | ||
* algorithm.py uses matplotlib, scipy, and numpy libraries and Python3. Be sure to download those. | ||
* For LaTeX editing, you could use Overleaf, but if you're using VS Code, download the LaTeX language support and LaTeX Workshop extensions and be sure to follow the installation instructions for LaTeX Workshop. | ||
* There is already a pre-compiled PDF of the LaTeX document provided in this repo called finalDocument.pdf as well as the source code for that document called finalDocument.tex. | ||
* Images of the plots are provided and they will also save a new one every time you run the Python code. If you don't want this to happen, be sure to comment out the lines where it saves the plots as PNGs. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
#Import libraries for data simulation and signal characterization | ||
import matplotlib.pyplot as plt | ||
import numpy as np | ||
from scipy import signal | ||
|
||
T0 = float(5.59e-6) #Calculated fundamental period | ||
omega = float(1124004.527) #Calculated fundamental angular frequency | ||
n = np.arange(1.00, 7.00, 1.00) #List with values of n (each harmonic) | ||
dutycycle = np.arange(0.00, 1.00, 0.01) #List with each percent of duty cycle | ||
spectrum = [] #Frequency spectrum x-axis values | ||
magnitude = [] #Magnitude values post-transform used in plotting y-axis for magnitude plot | ||
phase = [] #Phase values post-transform used in plotting y-axis for phase plot | ||
a0 = [] #Fourier constants throughout the frequency spectrum | ||
aharmonics = [] #List containing one list per harmonic that contains Fourier coefficients throughout the frequency spectrum | ||
jterms = [] #Calculated values from the imaginay term of the transformed equation | ||
realterms = [] #Calculated values from the real term of the transformed equation | ||
totals = [] #Final values calculated from the transformed equation | ||
t = [] #Time base on the x-axis | ||
|
||
#Improper definite integral setup | ||
intervalA1 = 0 #Lower limit of the first integral | ||
intervalB1 = float(T0) #Upper limit of the first integral | ||
intervalA2 = intervalB1 #Lower limit of the second integral | ||
intervalB2 = float(T0) #Upper limit of the second integral | ||
|
||
for j in range(len(n)): #Increment through each harmonic | ||
a = [] #Initialize a new Fourier coefficient list at the start of each loop | ||
for i in range(len(dutycycle)): #Increment through the frequency spectrum of the signal | ||
intervalB1 = T0*dutycycle[i] #Increment the upper limit of the first integral | ||
intervalB2 = T0*(1.00-dutycycle[i]) #Calculate and increment the upper limit of the second integral | ||
#Calculate the Fourier coefficients throughout the frequency spectrum and append it to the list for the current harmonic | ||
a.append(float((2/T0)*(omega*np.sin(n[j]*omega*intervalB1))-(omega*np.sin(n[j]*omega*intervalA1))-(omega*np.sin(n[j]*omega*intervalB2))+(omega*np.sin(n[j]*omega*intervalA2)))) | ||
a[i] = a[i]*(10.00**-9.00) #Convert the exponentials to integers | ||
aharmonics.append(a) #Append the list of Fourier coefficients of the current harmonic to the finalized list | ||
|
||
for i in range(len(dutycycle)): #Increment through the frequency spectrum | ||
intervalB1 = T0*dutycycle[i] #Increment the upper limit of the first integral | ||
intervalB2 = T0*(1.00-dutycycle[i]) #Calculate and increment the upper limit of the second integral | ||
a0.append(float((1/T0)*(intervalB1-intervalA1-intervalB2+intervalA2))) #Calculate the Fourier constant throughout the frequency spectrum | ||
t.append(intervalB2) #Creates the time base | ||
spectrum.append(float(1.00/intervalB2)) #Calculates and creates the frequency spectrum values | ||
realterms.append(float((3.00*np.sin(omega*t[i]))/omega)) #Calculates the values of the real terms | ||
jterms.append(float((1.00 + np.cos(omega*t[i]))/omega)) #Calculates the values of the imaginary terms | ||
totals.append((realterms[i]**2.00)+(jterms[i]**2.00)) #Calculates the sum of both terms, getting the final value | ||
phase.append(np.arctan(jterms[i]/realterms[i])) #Calculates the phase angle of the resulting vectors | ||
spectrum[i] = spectrum[i]*(10.00**-6.00) #Convert the exponentials to integers | ||
|
||
magnitude = np.sqrt(totals) #Calculate magnitudes of the vectors | ||
for i in range(len(magnitude)): #Increment through the frequency spectrum | ||
magnitude[i] = magnitude[i]*(10.00**6.00) #Convert the exponentials to integers | ||
|
||
#Create a plot showing the harmonics of the signal | ||
fig, harmonics = plt.subplots() | ||
|
||
harmonics.bar(x=spectrum, height=magnitude, color='maroon', width=0.1) | ||
plt.xlabel('Frequency (MHz)') | ||
plt.ylabel('Magnitude (udB)') | ||
plt.title('Harmonics of a 179 kHz PWM Square Wave') | ||
plt.grid() | ||
plt.savefig('harmonics.png') | ||
|
||
#Create a plot showing the phase of the signal | ||
fig, phasedata = plt.subplots() | ||
|
||
phasedata.plot(spectrum, phase, color='green') | ||
phasedata.set(xlabel='Frequency (MHz)', ylabel='Phase (Radians)', title='Phase of a 179 kHz PWM Square Wave on the Frequency Spectrum') | ||
plt.grid() | ||
plt.savefig('phase.png') | ||
|
||
#Create a plot showing the Fourier coefficients throughout the frequency spectrum | ||
fig, coefficients = plt.subplots() | ||
|
||
coefficients.plot(spectrum, a0, color='purple', label='A0') | ||
coefficients.plot(spectrum, aharmonics[0], color='blue', label='Fundamental') | ||
coefficients.plot(spectrum, aharmonics[1], color='yellow', label='First Harmonic') | ||
coefficients.plot(spectrum, aharmonics[2], color='red', label='Second Harmonic') | ||
coefficients.plot(spectrum, aharmonics[3], color='orange', label='Third Harmonic') | ||
coefficients.plot(spectrum, aharmonics[4], color='brown', label='Fourth Harmonic') | ||
coefficients.plot(spectrum, aharmonics[5], color='gray', label='Fifth Harmonic') | ||
coefficients.set(xlabel='Frequency (MHz)', ylabel='Amplitude (GV)', title='Fourier Coefficients Throughout the Frequency Spectrum') | ||
coefficients.legend() | ||
plt.grid() | ||
plt.savefig('coefficients.png') | ||
|
||
#Create a plot of the initial PWM square wave that we are characterizing | ||
fig, squarewave = plt.subplots() | ||
t = np.linspace(0, 3*T0, 10000, endpoint=False) | ||
frequency = 179000 | ||
squarewave.plot(t*1e6, signal.square(2*np.pi*t*frequency, duty=.25)) | ||
squarewave.set(xlabel='Time (us)', ylabel='Amplitude (V)', title='PWM Square Wave at 179 kHz and 25% Duty Cycle') | ||
plt.grid() | ||
plt.savefig('squarewave.png') | ||
|
||
plt.show() |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
\documentclass{article} | ||
\usepackage[utf8]{inputenc} | ||
\usepackage{amsmath, amssymb, amsthm} | ||
\usepackage{graphicx} | ||
\usepackage{witharrows} | ||
|
||
\title{PWM Simulation and Characterization} | ||
\author{Kadyn Belesca} | ||
\date{1/28/2024} | ||
|
||
\begin{document} | ||
|
||
\maketitle | ||
|
||
\newpage | ||
|
||
\section{PWM Defined as a Function of Duty Cycle} | ||
|
||
We can define a PWM signal with amplitudes of -1 to 1 as a function of duty cycle like so: | ||
|
||
\begin{equation} | ||
x(t) = | ||
\begin{cases} | ||
1 & 0 \leq t \leq \alpha{T_{0}} \\ | ||
-1 & \alpha{T_{0}} \leq t \leq T_{0}(1 - \alpha) \\ | ||
\end{cases} | ||
\end{equation} | ||
|
||
Where: | ||
|
||
\vspace{5mm} | ||
|
||
$T_{0} =$ Fundamental Period | ||
|
||
$\alpha =$ Duty Cycle | ||
|
||
\subsection{PWM Example} | ||
Figure 1 is an example of a PWM square wave signal at 179 kHz, which is my student ID number rounded up to 3 significant digits, | ||
at 25 percent duty cycle. For the following calculations, we will use this example at different duty cycles. | ||
\begin{figure}[h] | ||
\includegraphics[scale=.70]{squarewave.png} | ||
\caption{PWM Example} | ||
\end{figure} | ||
|
||
\newpage | ||
|
||
\subsection{Derivation of Frequency Spectra} | ||
|
||
We can derive the math defintion using a Fourier Transform to get the signal in the frequency spectra. | ||
Since this is a PWM square wave, we will need to setup an improper integral defining the amplitudes at | ||
their specified time intervals. | ||
|
||
\begin{gather*} | ||
\int_a^b \! x(t)e^{-j\omega{t}} \, \mathrm{d}t = \int_{a_1}^{b_1} \! 1e^{-j\omega{t}} \, \mathrm{d}t + \int_{a_2}^{b_2} \! -1e^{-j\omega{t}} \, \mathrm{d}t \\ | ||
= \int_{a_1}^{b_1} \! e^{-j\omega{t}} \, \mathrm{d}t - \int_{a_2}^{b_2} \! e^{-j\omega{t}} \, \mathrm{d}t \\ | ||
\text{We can pull out $\frac{1}{\omega{j}}$ from the resulting Riemann sums.} \\ | ||
= \frac{1}{\omega{j}}[[-e^{-\omega{jb_{1}}}+e^{-\omega{ja_{1}}}]+[e^{-\omega{jb_{2}}}+e^{-\omega{ja_{2}}}]] \\ | ||
\text{Then we can combine both Riemann sums into one whole} \\ | ||
\text{Riemann sum and use Euler's formula on the terms.} \\ | ||
= \frac{1}{\omega{j}}(-\cos{\omega{b_1}}-j\sin{\omega{b_1}}+\cos{\omega{a_1}}+j\sin{\omega{a_1}}+\cos{\omega{b_2}}+j\sin{\omega{b_2}}+\cos{\omega{a_2}}+j\sin{\omega{a_2}}) \\ | ||
\text{Since $b_1=a_2$ and $a_1=0$, we can cancel out some terms.} \\ | ||
= \frac{1}{\omega{j}}(1+\cos{\omega{b_2}}+j\sin{\omega{b_2}}) \\ | ||
\text{Using the following (adjusted) Euler's identity we can derive the complete Fourier transform.} \\ | ||
\sin{\omega} = \frac{1}{2j}(\cos{\omega}+j\sin{\omega}-\cos{\omega}+j\sin{\omega}) \\ | ||
\text{We can balance out the above equation with our equation we got in the previous integration.} \\ | ||
\sin{\omega{b_2}} = \frac{1}{2j}(\cos{\omega{b_2}}+j\sin{\omega{b_2}}-\cos{\omega{b_2}}+j\sin{\omega{b_2}}) \\ | ||
\text{First is to balance the $\frac{1}{2j}$ coefficient with the our coefficient} \\ | ||
\frac{2\sin{\omega{b_2}}}{\omega} = \frac{1}{\omega{j}}(\cos{\omega{b_2}}+j\sin{\omega{b_2}}-\cos{\omega{b_2}}+j\sin{\omega{b_2}}) \\ | ||
\text{Next, we expand the term on the right and add $\frac{1}{\omega{j}}$} \\ | ||
\frac{2\sin{\omega{b_2}}}{\omega}+\frac{1}{\omega{j}} = \frac{1}{\omega{j}} + \frac{\cos{\omega{b_2}}}{\omega{j}}+\frac{j\sin{\omega{b_2}}}{\omega{j}}-\frac{\cos{\omega{b_2}}}{\omega{j}}-\frac{j\sin{\omega{b_2}}}{\omega{j}} \\ | ||
\text{We can then add $\frac{\cos{\omega{b_2}}}{\omega{j}}+\frac{j\sin{\omega{b_2}}}{\omega{j}}$ to both sides,} \\ | ||
\text{cancel out some $j$'s, and combine like-terms to get the resulting Fourier transform:} \\ | ||
X(t) = \frac{3\sin{\omega{b_2}}}{\omega}-j\frac{1+\cos{\omega{b_2}}}{\omega} \\ | ||
\end{gather*} | ||
|
||
\subsection{Further Calculations and Explainations} | ||
|
||
From our equation $X(t) = \frac{3\sin{\omega{b_2}}}{\omega}-j\frac{1+\cos{\omega{b_2}}}{\omega}$, we can understand a few things. | ||
First, since $b_2 = T_0(1-\alpha)$, we can directly get the frequency value for each point by using the equation $\frac{1}{T}$, which is the equation | ||
for converting time to frequency. Since $b_2$ is a point in time from $0$ to $T_0$, we can replace $T$ with $b_2$ to get the resulting equation $\frac{1}{b_2}$ to get our x-values in the frequency domain. | ||
|
||
\vspace{5mm} | ||
|
||
For magnitude: $||\vec{X}(t)|| = \sqrt{{(\frac{3\sin{\omega{b_2}}}{\omega})}^2+{(\frac{1+\cos{\omega{b_2}}}{\omega})}^2}$ | ||
|
||
\vspace{5mm} | ||
|
||
For phase: $\theta = \tan^{-1}{\frac{\frac{1+\cos{\omega{b_2}}}{\omega}}{\frac{3\sin{\omega{b_2}}}{\omega}}}$ | ||
|
||
\begin{figure}[h] | ||
\includegraphics[scale=.70]{harmonics.png} | ||
\caption{Harmonics of the PWM Square Wave} | ||
\end{figure} | ||
|
||
\begin{figure}[h] | ||
\includegraphics[scale=.70]{phase.png} | ||
\caption{Phase of the PWM Square Wave} | ||
\end{figure} | ||
|
||
\begin{figure}[h] | ||
\includegraphics[scale=.70]{coefficients.png} | ||
\caption{Coefficients Throughout the Frequency Spectrum} | ||
\end{figure} | ||
|
||
\end{document} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.