This is the product of BALIGE ACADEMY TEAM: Vivian Siahaan and Rismon Hasiholan Sianipar.
SEMANGAT BELAJAR dan HORAS!!!
BALIGE CITY, NORTH SUMATERA
SUPPORT OUR YOUTUBE CHANNEL BY SUBSCRIBING:
FULL SOURCE CODE 4.0 (AMPLITUDE AND FREQUENCY MODULATION):
#main_program.py import tkinter as tk from main_form import Main_Form from plot_utils import Plot_Utils class Main_Program(): def __init__(self, root): self.initialize(root) def initialize(self, root): self.root = root width = 1560 height = 450 self.root.geometry(f"{width}x{height}") self.root.title("START FROM FROM SCRATCH SIGNAL AND IMAGE PROCESSING WITH TKINTER") #Creates necessary objects self.obj_main_form = Main_Form() self.obj_plot_utils = Plot_Utils() #Places widgets in root self.obj_main_form.add_widgets(self.root) #Binds events self.binds_event() def binds_event(self): self.obj_plot_utils.binds_simple_sinusoidal(self.obj_main_form) self.obj_plot_utils.binds_modulation(self.obj_main_form) if __name__ == "__main__": root = tk.Tk() app = Main_Program(root) root.mainloop() #main_form.py import tkinter as tk from tkinter import ttk from matplotlib.figure import Figure from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg class Main_Form: def add_widgets(self, root): #Adds menu self.add_menu(root) #Adds canvasses self.add_canvas(root) def add_menu(self, root): self.menu_bar = tk.Menu(root) #Creates a sinusoidal menu self.sinusoidal_menu = tk.Menu(self.menu_bar, tearoff=0) self.sinusoidal_menu.add_command(label="Simple Sinusoidal") self.sinusoidal_menu.add_command(label="Two Sinusoidals") self.sinusoidal_menu.add_command(label="More Two Sinusoidals") self.menu_bar.add_cascade(label="Sinusoidal Signals", menu=self.sinusoidal_menu) #Creates a modulation menu self.modulation = tk.Menu(self.menu_bar, tearoff=0) self.modulation.add_command(label="Amplitude Modulation") self.modulation.add_command(label="Frequency Modulation") self.menu_bar.add_cascade(label="Modulation", menu=self.modulation) root.config(menu=self.menu_bar) def add_canvas(self, root): #Menambahkan canvas1 widget pada root untuk menampilkan hasil self.figure1 = Figure(figsize=(15.2, 4.2), dpi=100) self.figure1.patch.set_facecolor('gray') self.canvas1 = FigureCanvasTkAgg(self.figure1, master=root) self.canvas1.get_tk_widget().grid(row=0, column=1, columnspan=1, rowspan=25, padx=5, pady=5, sticky="n") #form2.py import tkinter as tk from tkinter import ttk from matplotlib.figure import Figure from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg from signal_utils import Signal_Utils class Form2: def __init__(self, window): self.window = window width = 1520 height = 760 self.window.geometry(f"{width}x{height}") #Adds label widgets self.add_labels(self.window) #Adds entry widgets self.add_entries(self.window) #Adds canvasses self.add_canvas(self.window) #Adds button self.add_button(self.window) self.signal_utils = Signal_Utils() def add_labels(self, master): # Create two labels self.label1 = tk.Label(master, text="START") self.label1.grid(row=0, column=0, padx=5, pady=0.1, sticky="w") self.label2 = tk.Label(master, text="END") self.label2.grid(row=2, column=0, padx=5, pady=0.1, sticky="w") self.label3 = tk.Label(master, text="STEP") self.label3.grid(row=4, column=0, padx=5, pady=0.1, sticky="w") self.label4 = tk.Label(master, text="FREQUENCY 1") self.label4.grid(row=6, column=0, padx=5, pady=0.1, sticky="w") self.label5 = tk.Label(master, text="FREQUENCY 2") self.label5.grid(row=8, column=0, padx=5, pady=0.1, sticky="w") def add_entries(self, master): # Create an entry widget and place it in the first row, first column self.entry_start = tk.Entry(master, width=20, bg="cyan") self.entry_start.grid(row=1, column=0, padx=5, pady=0.1, sticky="n") self.entry_start.insert(0, "0") self.entry_start.bind('<Return>', self.plot_graph_event) # Create an entry widget and place it in the first row, first column self.entry_end = tk.Entry(master, width=20, bg="cyan") self.entry_end.grid(row=3, column=0, padx=5, pady=0.1, sticky="n") self.entry_end.insert(0, "1") self.entry_end.bind('<Return>', self.plot_graph_event) # Create an entry widget and place it in the first row, first column self.entry_step = tk.Entry(master, width=20, bg="cyan") self.entry_step.grid(row=5, column=0, padx=5, pady=0.1, sticky="n") self.entry_step.insert(0, "0.001") self.entry_step.bind('<Return>', self.plot_graph_event) # Create an entry widget and place it in the first row, first column self.entry_freq1 = tk.Entry(master, width=20, bg="cyan") self.entry_freq1.grid(row=7, column=0, padx=5, pady=0.1, sticky="n") self.entry_freq1.insert(0, "7") self.entry_freq1.bind('<Return>', self.plot_graph_event) # Create an entry widget and place it in the first row, first column self.entry_freq2 = tk.Entry(master, width=20, bg="cyan") self.entry_freq2.grid(row=9, column=0, padx=5, pady=0.1, sticky="n") self.entry_freq2.insert(0, "5") self.entry_freq2.bind('<Return>', self.plot_graph_event) def add_canvas(self, master): # Create a frame for canvas1 with a border frame1 = ttk.Frame(master, borderwidth=3, relief="groove") frame1.grid(row=0, column=1, columnspan=1, rowspan=25, padx=5, pady=5, sticky="n") # Adds canvas1 widget to frame1 self.figure1 = Figure(figsize=(13.7, 7.4), dpi=100) self.figure1.patch.set_facecolor('#F0F0F0') self.canvas1 = FigureCanvasTkAgg(self.figure1, master=frame1) self.canvas1.get_tk_widget().pack(fill=tk.BOTH, expand=True) def add_button(self, master): #Adds button self.btn1 = tk.Button(master, height=2, width=17, text="PLOT GRAPH", command=self.plot_graph) self.btn1.grid(row=10, column=0, padx=5, pady=1, sticky="n") def read_and_check_input(self, start, end, step, freq1, freq2): try: start = float(self.entry_start.get()) except ValueError: start = 0 self.entry_start.delete(0, tk.END) self.entry_start.insert(0, "0") try: end = float(self.entry_end.get()) except ValueError: end = 1 self.entry_end.delete(0, tk.END) self.entry_end.insert(0, "1") try: step = float(self.entry_step.get()) except ValueError: step = 0.001 self.entry_step.delete(0, tk.END) self.entry_step.insert(0, "0.001") try: freq1 = float(self.entry_freq1.get()) except ValueError: freq1 = 10 self.entry_freq1.delete(0, tk.END) self.entry_freq1.insert(0, "10") try: freq2 = float(self.entry_freq2.get()) except ValueError: freq2 = 5 self.entry_freq2.delete(0, tk.END) self.entry_freq2.insert(0, "5") return start, end, step, freq1, freq2 def plot_graph(self): start = self.entry_start.get() end = self.entry_end.get() step = self.entry_step.get() freq1 = self.entry_freq1.get() freq2 = self.entry_freq2.get() start, end, step, freq1, freq2 = self.read_and_check_input(start, end, step, freq1, freq2) self.signal_utils.more_two_sines(start, end, step, freq1, freq2, self.figure1, self.canvas1) def plot_graph_event(self, event): self.plot_graph() if __name__ == "__main__": window = tk.Tk() Form2(window) window.mainloop() #form1.py import tkinter as tk from tkinter import ttk from matplotlib.figure import Figure from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg class Form1: def __init__(self, window): self.window = window width = 1520 height = 760 self.window.geometry(f"{width}x{height}") #Adds canvasses self.add_canvas(self.window) def add_canvas(self, master): # Create a frame for canvas1 with a border frame1 = ttk.Frame(master, borderwidth=3, relief="groove") frame1.grid(row=0, column=0, columnspan=1, rowspan=25, padx=5, pady=5, sticky="n") # Adds canvas1 widget to frame1 self.figure1 = Figure(figsize=(15, 7.4), dpi=100) self.figure1.patch.set_facecolor('#F0F0F0') self.canvas1 = FigureCanvasTkAgg(self.figure1, master=frame1) self.canvas1.get_tk_widget().pack(fill=tk.BOTH, expand=True) if __name__ == "__main__": window = tk.Tk() Form1(window) window.mainloop() #signal_utils.py import matplotlib.pyplot as plt import numpy as np class Signal_Utils: def __init__(self): pass def simple_sine(self, figure, canvas): figure.clear() start = 0 end = 1 step = 0.001 x = np.arange(float(start), float(end), float(step)) Fs = 10 y = np.sin(2*np.pi*float(Fs)*x) ax = figure.add_subplot(1,1,1) ax.plot(x, y, linewidth=5.0, color='red') ax.set_ylabel('Amplitude', color='blue') ax.set_xlabel('Time (second)', color='blue') ax.set_title(f'Simple Sinusoidal Graph (Frequency = {Fs} Hz)') ax.set_facecolor('#F0F0F0') ax.grid(True) figure.tight_layout() canvas.draw() def two_sines(self, figure, canvas): figure.clear() start = 0 end = 1 step = 0.001 x = np.arange(float(start), float(end), float(step)) Fs1 = 10 Fs2 = 6 y1 = np.sin(2*np.pi*float(Fs1)*x) y2 = np.cos(2*np.pi*float(Fs2)*x) ax1 = figure.add_subplot(2,2,1) ax1.plot(x, y1, linewidth=3.0, color='red', label=f'Sin(2*pi*{Fs1}*x)') ax1.plot(x, y2, linewidth=3.0, color='black', label=f'Cos(2*pi*{Fs2}*x)') ax1.set_ylabel('Amplitude', color='blue') ax1.set_xlabel('Time (second)', color='blue') ax1.set_title(f'Sin(2*pi*{Fs1}*x) and Cos(2*pi*{Fs2}*x)') ax1.set_facecolor('#F0F0F0') ax1.legend() ax1.grid(True) ax2 = figure.add_subplot(2,2,2) ax2.plot(x, y1*y2, linewidth=3.0, color='green') ax2.set_ylabel('Amplitude', color='blue') ax2.set_xlabel('Time (second)', color='blue') ax2.set_title(f'Sin(2*pi*{Fs1}*x) * Cos(2*pi*{Fs2}*x)') ax2.set_facecolor('#F0F0F0') ax2.grid(True) ax3 = figure.add_subplot(2,2,3) ax3.plot(x, y1 + y2, linewidth=3.0, color='brown') ax3.set_ylabel('Amplitude', color='blue') ax3.set_xlabel('Time (second)', color='blue') ax3.set_title(f'Sin(2*pi*{Fs1}*x) + Cos(2*pi*{Fs2}*x)') ax3.set_facecolor('#F0F0F0') ax3.grid(True) ax4 = figure.add_subplot(2,2,4) ax4.plot(x, y1 - y2, linewidth=3.0, color='blue') ax4.set_ylabel('Amplitude', color='blue') ax4.set_xlabel('Time (second)', color='blue') ax4.set_title(f'Sin(2*pi*{Fs1}*x) - Cos(2*pi*{Fs2}*x)') ax4.set_facecolor('#F0F0F0') ax4.grid(True) figure.tight_layout() canvas.draw() def more_two_sines(self, start=0, end=1, step=0.001, Fs1=7, Fs2=5, figure=None, canvas=None): figure.clear() x = np.arange(float(start), float(end), float(step)) y1 = np.sin(2*np.pi*float(Fs1)*x) y2 = np.cos(2*np.pi*float(Fs2)*x) ax1 = figure.add_subplot(2,2,1) ax1.plot(x, y1, linewidth=3.0, color='red', label=f'Sin(2*pi*{Fs1}*x)') ax1.plot(x, y2, linewidth=3.0, color='black', label=f'Cos(2*pi*{Fs2}*x)') ax1.set_ylabel('Amplitude', color='blue') ax1.set_xlabel('Time (second)', color='blue') ax1.set_title(f'Sin(2*pi*{Fs1}*x) and Cos(2*pi*{Fs2}*x)') ax1.set_facecolor('#F0F0F0') ax1.legend() ax1.grid(True) ax2 = figure.add_subplot(2,2,2) ax2.plot(x, y1*y2, linewidth=3.0, color='green') ax2.set_ylabel('Amplitude', color='blue') ax2.set_xlabel('Time (second)', color='blue') ax2.set_title(f'Sin(2*pi*{Fs1}*x) * Cos(2*pi*{Fs2}*x)') ax2.set_facecolor('#F0F0F0') ax2.grid(True) ax3 = figure.add_subplot(2,2,3) ax3.plot(x, y1 + y2, linewidth=3.0, color='brown') ax3.set_ylabel('Amplitude', color='blue') ax3.set_xlabel('Time (second)', color='blue') ax3.set_title(f'Sin(2*pi*{Fs1}*x) + Cos(2*pi*{Fs2}*x)') ax3.set_facecolor('#F0F0F0') ax3.grid(True) ax4 = figure.add_subplot(2,2,4) ax4.plot(x, y1 - y2, linewidth=3.0, color='blue') ax4.set_ylabel('Amplitude', color='blue') ax4.set_xlabel('Time (second)', color='blue') ax4.set_title(f'Sin(2*pi*{Fs1}*x) - Cos(2*pi*{Fs2}*x)') ax4.set_facecolor('#F0F0F0') ax4.grid(True) figure.tight_layout() canvas.draw() #plot_utils.py import matplotlib.pyplot as plt import tkinter as tk from tkinter import * import seaborn as sns import numpy as np import pandas as pd from form1 import Form1 from form2 import Form2 from form_am import Form_AM from form_fm import Form_FM from signal_utils import Signal_Utils from am_utils import AM_Utils from fm_utils import FM_Utils class Plot_Utils: def __init__(self): self.signal_utils = Signal_Utils() self.am_utils = AM_Utils() self.fm_utils = FM_Utils() def plot_simple_sine(self): win = tk.Toplevel() form1 = Form1(win) win.title("Simple Sinusoidal Signal") self.signal_utils.simple_sine(form1.figure1, form1.canvas1) def plot_two_sines(self): win = tk.Toplevel() form1 = Form1(win) win.title("Two Simple Sinusoidal Signals") self.signal_utils.two_sines(form1.figure1, form1.canvas1) def plot_more_two_sines(self): win = tk.Toplevel() win.title("MANIPULATING SINUSOIDAL SIGNALS") form2 = Form2(win) start = float(form2.entry_start.get()) end = float(form2.entry_end.get()) step = float(form2.entry_step.get()) freq1 = float(form2.entry_freq1.get()) freq2 = float(form2.entry_freq2.get()) self.signal_utils.more_two_sines(start, end, step, freq1, freq2, form2.figure1, form2.canvas1) def binds_simple_sinusoidal(self, window): window.sinusoidal_menu.entryconfigure("Simple Sinusoidal", command =lambda:self.plot_simple_sine()) window.sinusoidal_menu.entryconfigure("Two Sinusoidals", command =lambda:self.plot_two_sines()) window.sinusoidal_menu.entryconfigure("More Two Sinusoidals", command =lambda:self.plot_more_two_sines()) def plot_amplitude_modulation(self): win = tk.Toplevel() win.title("AMPLITUDE MODULATION") form_am = Form_AM(win) form_am.plot_fft_am() form_am.plot_graph() def plot_frequency_modulation(self): win = tk.Toplevel() win.title("FREQUENCY MODULATION") form_fm = Form_FM(win) form_fm.plot_fft_fm() form_fm.plot_graph() def binds_modulation(self, window): window.modulation.entryconfigure("Amplitude Modulation", command =lambda:self.plot_amplitude_modulation()) window.modulation.entryconfigure("Frequency Modulation", command =lambda:self.plot_frequency_modulation()) #form_am.py import tkinter as tk from tkinter import ttk from matplotlib.figure import Figure from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg from am_utils import AM_Utils from form1 import Form1 class Form_AM: def __init__(self, window): self.window = window width = 1520 height = 760 self.window.geometry(f"{width}x{height}") #Adds label widgets self.add_labels(self.window) #Adds entry widgets self.add_entries(self.window) #Adds canvasses self.add_canvas(self.window) #Adds button self.add_button(self.window) self.am_utils = AM_Utils() def add_labels(self, master): # Create two labels self.label1 = tk.Label(master, text="SAMPLING FREQUENCY") self.label1.grid(row=0, column=0, padx=5, pady=0.1, sticky="w") self.label2 = tk.Label(master, text="TIME PERIODE") self.label2.grid(row=2, column=0, padx=5, pady=0.1, sticky="w") self.label3 = tk.Label(master, text="CARRIER AMPLITUDE") self.label3.grid(row=4, column=0, padx=5, pady=0.1, sticky="w") self.label4 = tk.Label(master, text="CARRIER FREQUENCY") self.label4.grid(row=6, column=0, padx=5, pady=0.1, sticky="w") self.label5 = tk.Label(master, text="MODULATING AMPLITUDE") self.label5.grid(row=8, column=0, padx=5, pady=0.1, sticky="w") self.label6 = tk.Label(master, text="MODULATING FREQUENCY") self.label6.grid(row=10, column=0, padx=5, pady=0.1, sticky="w") self.label7 = tk.Label(master, text="IDX MOD:", font=("Helvetica", 10)) self.label7.grid(row=15, column=0, padx=5, pady=0.1, sticky="w") def add_entries(self, master): # Create entry widgets self.entry_fs = tk.Entry(master, width=20, bg="cyan") self.entry_fs.grid(row=1, column=0, padx=5, pady=0.1, sticky="n") self.entry_fs.insert(0, "1000") self.entry_fs.bind('<Return>', self.plot_graph_event) self.entry_periode = tk.Entry(master, width=20, bg="cyan") self.entry_periode.grid(row=3, column=0, padx=5, pady=0.1, sticky="n") self.entry_periode.insert(0, "1") self.entry_periode.bind('<Return>', self.plot_graph_event) self.entry_ac = tk.Entry(master, width=20, bg="cyan") self.entry_ac.grid(row=5, column=0, padx=5, pady=0.1, sticky="n") self.entry_ac.insert(0, "1") self.entry_ac.bind('<Return>', self.plot_graph_event) self.entry_fc = tk.Entry(master, width=20, bg="cyan") self.entry_fc.grid(row=7, column=0, padx=5, pady=0.1, sticky="n") self.entry_fc.insert(0, "50") self.entry_fc.bind('<Return>', self.plot_graph_event) self.entry_am = tk.Entry(master, width=20, bg="cyan") self.entry_am.grid(row=9, column=0, padx=5, pady=0.1, sticky="n") self.entry_am.insert(0, "1") self.entry_am.bind('<Return>', self.plot_graph_event) self.entry_fm = tk.Entry(master, width=20, bg="cyan") self.entry_fm.grid(row=11, column=0, padx=5, pady=0.1, sticky="n") self.entry_fm.insert(0, "5") self.entry_fm.bind('<Return>', self.plot_graph_event) def add_canvas(self, master): # Create a frame for canvas1 with a border frame1 = ttk.Frame(master, borderwidth=3, relief="groove") frame1.grid(row=0, column=1, columnspan=1, rowspan=25, padx=5, pady=5, sticky="n") # Adds canvas1 widget to frame1 self.figure1 = Figure(figsize=(13.2, 7.4), dpi=100) self.figure1.patch.set_facecolor('#F0F0F0') self.canvas1 = FigureCanvasTkAgg(self.figure1, master=frame1) self.canvas1.get_tk_widget().pack(fill=tk.BOTH, expand=True) def add_button(self, master): #Adds button self.btn1 = tk.Button(master, height=2, width=17, text="PLOT GRAPH", command=self.plot_graph) self.btn1.grid(row=12, column=0, padx=5, pady=1, sticky="n") self.btn2 = tk.Button(master, height=2, width=17, text="PLOT FFT", command=self.plot_fft_am) self.btn2.grid(row=13, column=0, padx=5, pady=1, sticky="n") self.btn3 = tk.Button(master, height=2, width=17, text="PLOT DB", command=self.plot_fft_am_db) self.btn3.grid(row=14, column=0, padx=5, pady=1, sticky="n") def read_and_check_input(self, fs, T, ac, fc, am, fm): try: fsampling = float(fs) except ValueError: fsampling = 1000 self.entry_fs.delete(0, tk.END) self.entry_fs.insert(0, "1000") try: periode = float(T) except ValueError: periode = 1 self.entry_periode.delete(0, tk.END) self.entry_periode.insert(0, "1") try: amp_carrier = float(ac) except ValueError: amp_carrier = 1 self.entry_ac.delete(0, tk.END) self.entry_ac.insert(0, "1") try: freq_carrier = float(fc) except ValueError: freq_carrier = 50 self.entry_fc.delete(0, tk.END) self.entry_fc.insert(0, "50") try: amp_mod = float(am) except ValueError: amp_mod = 1 self.entry_am.delete(0, tk.END) self.entry_am.insert(0, "1") try: freq_mod = float(fm) except ValueError: freq_mod = 5 self.entry_fm.delete(0, tk.END) self.entry_fm.insert(0, "5") return fsampling, periode, amp_carrier, freq_carrier, amp_mod, freq_mod def plot_graph(self): #Reads AM params fsampling = self.entry_fs.get() periode = self.entry_periode.get() amp_carrier = self.entry_ac.get() freq_carrier = self.entry_fc.get() amp_mod = self.entry_am.get() freq_mod = self.entry_fm.get() #Change text in label7 for index modulation miu=float(amp_mod)/float(amp_carrier) self.label7.config(text=f"IDX MOD: {miu:.2f}", font=("Helvetica", 12, "bold")) Fs, T, Ac, Fc, Am, Fm = self.read_and_check_input(fsampling, periode, amp_carrier, freq_carrier, amp_mod, freq_mod) # Performs amplitude modulation t, carrier_wave, modulating_wave, am_signal = self.am_utils.calculate_amplitude_modulation(Fs, T, Ac, Fc, Am, Fm) title1 = f'Carrier Signal, frequency = {Fc}, Amplitude = {Ac}' title2 = f'Modulating Signal, frequency = {Fm}, Amplitude = {Am}' title3 = "Amplitude Modulated Signal" self.am_utils.time_domain(t, carrier_wave, title1, modulating_wave, title2, am_signal, title3, self.figure1, self.canvas1) def plot_graph_event(self, event): self.plot_graph() def plot_fft_am(self): #Plots FFT of signals in form1 win2 = tk.Toplevel() win2.title("AMPLITUDE MODULATION (FREQUENCY-DOMAIN)") form1 = Form1(win2) #Reads AM params fsampling = self.entry_fs.get() periode = self.entry_periode.get() amp_carrier = self.entry_ac.get() freq_carrier = self.entry_fc.get() amp_mod = self.entry_am.get() freq_mod = self.entry_fm.get() Fs, T, Ac, Fc, Am, Fm = self.read_and_check_input(fsampling, periode, amp_carrier, freq_carrier, amp_mod, freq_mod) # Performs amplitude modulation t, carrier_wave, modulating_wave, am_signal = self.am_utils.calculate_amplitude_modulation(Fs, T, Ac, Fc, Am, Fm) self.am_utils.plot_fft_signal(Fs, carrier_wave, \ "FFT of Carrier Signal", modulating_wave, "FFT of Modulating Signal", am_signal, "FFT of AM Signal", form1.figure1, form1.canvas1) def plot_fft_am_db(self): #Plots FFT of signals in form1 win2 = tk.Toplevel() win2.title("AMPLITUDE MODULATION (FREQUENCY-DOMAIN) with DECIBLE MAGNITUDE") form1 = Form1(win2) #Reads AM params fsampling = self.entry_fs.get() periode = self.entry_periode.get() amp_carrier = self.entry_ac.get() freq_carrier = self.entry_fc.get() amp_mod = self.entry_am.get() freq_mod = self.entry_fm.get() Fs, T, Ac, Fc, Am, Fm = self.read_and_check_input(fsampling, periode, amp_carrier, freq_carrier, amp_mod, freq_mod) # Performs amplitude modulation t, carrier_wave, modulating_wave, am_signal = self.am_utils.calculate_amplitude_modulation(Fs, T, Ac, Fc, Am, Fm) self.am_utils.plot_fft_db(Fs, carrier_wave, \ "Decible Magnitude of Carrier Signal", modulating_wave, "Decible Magnitude of Modulating Signal", am_signal, "Decible Magnitude of AM Signal", form1.figure1, form1.canvas1) if __name__ == "__main__": window = tk.Tk() Form_AM(window) window.mainloop() #am_utils.py import matplotlib.pyplot as plt import numpy as np class AM_Utils: def __init__(self): pass def calculate_amplitude_modulation(self, Fs, T, Ac, Fc, Am, Fm): # Define time line t = np.arange(0, T, 1/Fs) # Carrier signal carrier_wave = Ac*np.cos(2*np.pi*Fc*t) # Modulating signal modulating_wave = Am*np.cos(2*np.pi*Fm*t) # Amplitude modulation miu = Am/Ac am_signal = Ac*(1 + miu*np.cos(2*np.pi*Fm*t)) * np.cos(2*np.pi*Fc*t) return t, carrier_wave, modulating_wave, am_signal def time_domain(self, t, carrier_wave, title1, modulating_wave, title2, am_signal, title3, figure=None, canvas=None): figure.clear() ax1 = figure.add_subplot(3,1,1) ax1.plot(t, carrier_wave, linewidth=3.0, color='red') ax1.set_ylabel('Amplitude', color='blue') ax1.set_xlabel('Time (second)', color='blue') ax1.set_title(title1) ax1.set_facecolor('#F0F0F0') ax1.grid(True) ax2 = figure.add_subplot(3,1,2) ax2.plot(t, modulating_wave, linewidth=3.0, color='black') ax2.set_ylabel('Amplitude', color='blue') ax2.set_xlabel('Time (second)', color='blue') ax2.set_title(title2) ax2.set_facecolor('#F0F0F0') ax2.grid(True) ax3 = figure.add_subplot(3,1,3) ax3.plot(t, am_signal, linewidth=3.0, color='blue') ax3.set_ylabel('Amplitude', color='blue') ax3.set_xlabel('Time (second)', color='blue') ax3.set_title(title3) ax3.set_facecolor('#F0F0F0') ax3.grid(True) figure.tight_layout() canvas.draw() def fft_signal(self, Fs, signal): # Perform FFT fft_result = np.fft.fft(signal) freqs = np.fft.fftfreq(len(signal), 1/Fs) # Keep only positive frequencies pos_freqs = freqs[:len(freqs)//2] pos_fft_result = fft_result[:len(fft_result)//2] return pos_freqs, pos_fft_result def fft_db(self, Fs, signal): # Apply Hamming window windowed_signal = signal * np.hamming(len(signal)) # Perform FFT and converts its magnitude to decibel fft_result = np.fft.fft(windowed_signal) # Handle cases where fft_result is zero magnitude_dB = np.zeros_like(fft_result) non_zero_indices = np.abs(fft_result) > 0.01 magnitude_dB[non_zero_indices] = 20*np.log10(np.abs(fft_result[non_zero_indices])) freqs = np.fft.fftfreq(len(signal), 1/Fs) # Keep only positive frequencies pos_freqs = freqs[:len(freqs)//2] pos_magnitude_dB = magnitude_dB[:len(magnitude_dB)//2] return pos_freqs, pos_magnitude_dB def plot_fft_signal(self, Fs, signal1, title1, signal2, title2, signal3, title3, figure=None, canvas=None): figure.clear() #Calculate FFT freqs1, fft_result1 = self.fft_signal(Fs, signal1) freqs2, fft_result2 = self.fft_signal(Fs, signal2) freqs3, fft_result3 = self.fft_signal(Fs, signal3) ax1 = figure.add_subplot(3,1,1) ax1.plot(freqs1, np.abs(fft_result1), linewidth=2.0, color='red') ax1.set_ylabel('Magnitude', color='blue') ax1.set_xlabel('Frequency (Hz)', color='blue') ax1.set_title(title1) ax1.set_xticks(np.arange(min(freqs1), max(freqs1)+1, step=100)) ax1.set_facecolor('#F0F0F0') ax1.grid(True) ax2 = figure.add_subplot(3,1,2) ax2.plot(freqs2, np.abs(fft_result2), linewidth=2.0, color='black') ax2.set_ylabel('Magnitude', color='blue') ax2.set_xlabel('Frequency (Hz)', color='blue') ax2.set_title(title2) ax2.set_facecolor('#F0F0F0') ax2.set_xticks(np.arange(min(freqs1), max(freqs2)+1, step=100)) ax2.grid(True) ax3 = figure.add_subplot(3,1,3) ax3.plot(freqs3, np.abs(fft_result3), linewidth=2.0, color='blue') ax3.set_ylabel('Magnitude', color='blue') ax3.set_xlabel('Frequency (Hz)', color='blue') ax3.set_title(title3) ax3.set_facecolor('#F0F0F0') ax3.set_xticks(np.arange(min(freqs1), max(freqs3)+1, step=100)) ax3.grid(True) figure.tight_layout() canvas.draw() def plot_fft_db(self, Fs, signal1, title1, signal2, title2, signal3, title3, figure=None, canvas=None): figure.clear() #Calculate FFT freqs1, fft_result1 = self.fft_db(Fs, signal1) freqs2, fft_result2 = self.fft_db(Fs, signal2) freqs3, fft_result3 = self.fft_db(Fs, signal3) ax1 = figure.add_subplot(3,1,1) ax1.plot(freqs1, np.abs(fft_result1), linewidth=2.0, color='red') ax1.set_ylabel('Magnitude Spectrum (dB)', color='blue') ax1.set_xlabel('Frequency (Hz)', color='blue') ax1.set_title(title1) ax1.set_xticks(np.arange(min(freqs1), max(freqs1)+1, step=100)) ax1.set_facecolor('#F0F0F0') ax1.grid(True) ax2 = figure.add_subplot(3,1,2) ax2.plot(freqs2, np.abs(fft_result2), linewidth=2.0, color='black') ax2.set_ylabel('Magnitude Spectrum (dB)', color='blue') ax2.set_xlabel('Frequency (Hz)', color='blue') ax2.set_title(title2) ax2.set_facecolor('#F0F0F0') ax2.set_xticks(np.arange(min(freqs1), max(freqs2)+1, step=100)) ax2.grid(True) ax3 = figure.add_subplot(3,1,3) ax3.plot(freqs3, np.abs(fft_result3), linewidth=2.0, color='blue') ax3.set_ylabel('Magnitude Spectrum (dB)', color='blue') ax3.set_xlabel('Frequency (Hz)', color='blue') ax3.set_title(title3) ax3.set_facecolor('#F0F0F0') ax3.set_xticks(np.arange(min(freqs1), max(freqs3)+1, step=100)) ax3.grid(True) figure.tight_layout() canvas.draw() #fm_utils.py import matplotlib.pyplot as plt import numpy as np class FM_Utils: def __init__(self): pass def calculate_frequency_modulation(self, beta, Fs, T, Ac, Fc, Am, Fm): # Defines time line t = np.arange(0, T, 1/Fs) # Carrier signal carrier_wave = Ac*np.sin(2*np.pi*Fc*t) # Modulating signal modulating_wave = Am*np.sin(2*np.pi*Fm*t) # Frequency modulation #beta is modulation index fm_signal = Ac*np.sin(2*np.pi*Fc*t + beta*modulating_wave) return t, carrier_wave, modulating_wave, fm_signal #form_fm.py import tkinter as tk from tkinter import ttk from matplotlib.figure import Figure from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg from am_utils import AM_Utils from fm_utils import FM_Utils from form1 import Form1 class Form_FM: def __init__(self, window): self.window = window width = 1520 height = 760 self.window.geometry(f"{width}x{height}") #Adds label widgets self.add_labels(self.window) #Adds entry widgets self.add_entries(self.window) #Adds canvasses self.add_canvas(self.window) #Adds button self.add_button(self.window) #Creates neccesary objects self.am_utils = AM_Utils() self.fm_utils = FM_Utils() def add_labels(self, master): # Create two labels self.label1 = tk.Label(master, text="SAMPLING FREQUENCY") self.label1.grid(row=0, column=0, padx=5, pady=0.1, sticky="w") self.label2 = tk.Label(master, text="TIME PERIODE") self.label2.grid(row=2, column=0, padx=5, pady=0.1, sticky="w") self.label3 = tk.Label(master, text="CARRIER AMPLITUDE") self.label3.grid(row=4, column=0, padx=5, pady=0.1, sticky="w") self.label4 = tk.Label(master, text="CARRIER FREQUENCY") self.label4.grid(row=6, column=0, padx=5, pady=0.1, sticky="w") self.label5 = tk.Label(master, text="MODULATING AMPLITUDE") self.label5.grid(row=8, column=0, padx=5, pady=0.1, sticky="w") self.label6 = tk.Label(master, text="MODULATING FREQUENCY") self.label6.grid(row=10, column=0, padx=5, pady=0.1, sticky="w") self.label7 = tk.Label(master, text="IDX MODULATION:") self.label7.grid(row=12, column=0, padx=5, pady=0.1, sticky="w") def add_entries(self, master): # Create entry widgets self.entry_fs = tk.Entry(master, width=20, bg="cyan") self.entry_fs.grid(row=1, column=0, padx=5, pady=0.1, sticky="n") self.entry_fs.insert(0, "1000") self.entry_fs.bind('<Return>', self.plot_graph_event) self.entry_periode = tk.Entry(master, width=20, bg="cyan") self.entry_periode.grid(row=3, column=0, padx=5, pady=0.1, sticky="n") self.entry_periode.insert(0, "1") self.entry_periode.bind('<Return>', self.plot_graph_event) self.entry_ac = tk.Entry(master, width=20, bg="cyan") self.entry_ac.grid(row=5, column=0, padx=5, pady=0.1, sticky="n") self.entry_ac.insert(0, "1") self.entry_ac.bind('<Return>', self.plot_graph_event) self.entry_fc = tk.Entry(master, width=20, bg="cyan") self.entry_fc.grid(row=7, column=0, padx=5, pady=0.1, sticky="n") self.entry_fc.insert(0, "50") self.entry_fc.bind('<Return>', self.plot_graph_event) self.entry_am = tk.Entry(master, width=20, bg="cyan") self.entry_am.grid(row=9, column=0, padx=5, pady=0.1, sticky="n") self.entry_am.insert(0, "1") self.entry_am.bind('<Return>', self.plot_graph_event) self.entry_fm = tk.Entry(master, width=20, bg="cyan") self.entry_fm.grid(row=11, column=0, padx=5, pady=0.1, sticky="n") self.entry_fm.insert(0, "5") self.entry_fm.bind('<Return>', self.plot_graph_event) self.entry_idx_mod = tk.Entry(master, width=20, bg="cyan") self.entry_idx_mod.grid(row=13, column=0, padx=5, pady=0.1, sticky="n") self.entry_idx_mod.insert(0, "5") self.entry_idx_mod.bind('<Return>', self.plot_graph_event) def add_canvas(self, master): # Create a frame for canvas1 with a border frame1 = ttk.Frame(master, borderwidth=3, relief="groove") frame1.grid(row=0, column=1, columnspan=1, rowspan=25, padx=5, pady=5, sticky="n") # Adds canvas1 widget to frame1 self.figure1 = Figure(figsize=(13.2, 7.4), dpi=100) self.figure1.patch.set_facecolor('#F0F0F0') self.canvas1 = FigureCanvasTkAgg(self.figure1, master=frame1) self.canvas1.get_tk_widget().pack(fill=tk.BOTH, expand=True) def add_button(self, master): #Adds button self.btn1 = tk.Button(master, height=2, width=17, text="PLOT GRAPH", command=self.plot_graph) self.btn1.grid(row=14, column=0, padx=5, pady=1, sticky="n") self.btn2 = tk.Button(master, height=2, width=17, text="PLOT FFT", command=self.plot_fft_fm) self.btn2.grid(row=15, column=0, padx=5, pady=1, sticky="n") self.btn3 = tk.Button(master, height=2, width=17, text="PLOT DB", command=self.plot_fft_fm_db) self.btn3.grid(row=16, column=0, padx=5, pady=1, sticky="n") def read_and_check_input(self, beta, fs, T, ac, fc, am, fm): try: idx_mod = float(beta) except ValueError: idx_mod = 5 self.entry_idx_mod.delete(0, tk.END) self.entry_idx_mod.insert(0, "5") try: fsampling = float(fs) except ValueError: fsampling = 1000 self.entry_fs.delete(0, tk.END) self.entry_fs.insert(0, "1000") try: periode = float(T) except ValueError: periode = 1 self.entry_periode.delete(0, tk.END) self.entry_periode.insert(0, "1") try: amp_carrier = float(ac) except ValueError: amp_carrier = 1 self.entry_ac.delete(0, tk.END) self.entry_ac.insert(0, "1") try: freq_carrier = float(fc) except ValueError: freq_carrier = 50 self.entry_fc.delete(0, tk.END) self.entry_fc.insert(0, "50") try: amp_mod = float(am) except ValueError: amp_mod = 1 self.entry_am.delete(0, tk.END) self.entry_am.insert(0, "1") try: freq_mod = float(fm) except ValueError: freq_mod = 5 self.entry_fm.delete(0, tk.END) self.entry_fm.insert(0, "5") return idx_mod, fsampling, periode, amp_carrier, freq_carrier, amp_mod, freq_mod def plot_graph(self): #Reads FM params idx_mod = self.entry_idx_mod.get() fsampling = self.entry_fs.get() periode = self.entry_periode.get() amp_carrier = self.entry_ac.get() freq_carrier = self.entry_fc.get() amp_mod = self.entry_am.get() freq_mod = self.entry_fm.get() beta, Fs, T, Ac, Fc, Am, Fm = self.read_and_check_input(idx_mod, fsampling, periode, amp_carrier, freq_carrier, amp_mod, freq_mod) # Performs frequency modulation t, carrier_wave, modulating_wave, fm_signal = self.fm_utils.calculate_frequency_modulation(beta, Fs, T, Ac, Fc, Am, Fm) title1 = f'Carrier Signal, frequency = {Fc}, Amplitude = {Ac}' title2 = f'Modulating Signal, frequency = {Fm}, Amplitude = {Am}' title3 = "Frequency Modulated Signal" self.am_utils.time_domain(t, carrier_wave, title1, modulating_wave, title2, fm_signal, title3, self.figure1, self.canvas1) def plot_graph_event(self, event): self.plot_graph() def plot_fft_fm(self): #Plots FFT of signals in form1 win2 = tk.Toplevel() win2.title("AMPLITUDE MODULATION (FREQUENCY-DOMAIN)") form1 = Form1(win2) #Reads FM params idx_mod = self.entry_idx_mod.get() fsampling = self.entry_fs.get() periode = self.entry_periode.get() amp_carrier = self.entry_ac.get() freq_carrier = self.entry_fc.get() amp_mod = self.entry_am.get() freq_mod = self.entry_fm.get() beta, Fs, T, Ac, Fc, Am, Fm = self.read_and_check_input(idx_mod, fsampling, periode, amp_carrier, freq_carrier, amp_mod, freq_mod) # Performs frequency modulation t, carrier_wave, modulating_wave, am_signal = self.fm_utils.calculate_frequency_modulation(beta, Fs, T, Ac, Fc, Am, Fm) self.am_utils.plot_fft_signal(Fs, carrier_wave, \ "FFT of Carrier Signal", modulating_wave, "FFT of Modulating Signal", am_signal, "FFT of FM Signal", form1.figure1, form1.canvas1) def plot_fft_fm_db(self): #Plots FFT of signals in form1 win2 = tk.Toplevel() win2.title("AMPLITUDE MODULATION (FREQUENCY-DOMAIN) with DECIBLE MAGNITUDE") form1 = Form1(win2) #Reads FM params idx_mod = self.entry_idx_mod.get() fsampling = self.entry_fs.get() periode = self.entry_periode.get() amp_carrier = self.entry_ac.get() freq_carrier = self.entry_fc.get() amp_mod = self.entry_am.get() freq_mod = self.entry_fm.get() beta, Fs, T, Ac, Fc, Am, Fm = self.read_and_check_input(idx_mod, fsampling, periode, amp_carrier, freq_carrier, amp_mod, freq_mod) # Performs amplitude modulation t, carrier_wave, modulating_wave, am_signal = self.fm_utils.calculate_frequency_modulation(beta, Fs, T, Ac, Fc, Am, Fm) self.am_utils.plot_fft_db(Fs, carrier_wave, \ "Decible Magnitude of Carrier Signal", modulating_wave, "Decible Magnitude of Modulating Signal", am_signal, "Decible Magnitude of FM Signal", form1.figure1, form1.canvas1) if __name__ == "__main__": window = tk.Tk() Form_FM(window) window.mainloop()
FULL SOURCE CODE 5.0 (PHASE MODULATION):
#main_program.py import tkinter as tk from main_form import Main_Form from plot_utils import Plot_Utils class Main_Program(): def __init__(self, root): self.initialize(root) def initialize(self, root): self.root = root width = 1560 height = 450 self.root.geometry(f"{width}x{height}") self.root.title("START FROM FROM SCRATCH SIGNAL AND IMAGE PROCESSING WITH TKINTER") #Creates necessary objects self.obj_main_form = Main_Form() self.obj_plot_utils = Plot_Utils() #Places widgets in root self.obj_main_form.add_widgets(self.root) #Binds events self.binds_event() def binds_event(self): self.obj_plot_utils.binds_simple_sinusoidal(self.obj_main_form) self.obj_plot_utils.binds_modulation(self.obj_main_form) if __name__ == "__main__": root = tk.Tk() app = Main_Program(root) root.mainloop() #main_form.py import tkinter as tk from tkinter import ttk from matplotlib.figure import Figure from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg class Main_Form: def add_widgets(self, root): #Adds menu self.add_menu(root) #Adds canvasses self.add_canvas(root) def add_menu(self, root): self.menu_bar = tk.Menu(root) #Creates a sinusoidal menu self.sinusoidal_menu = tk.Menu(self.menu_bar, tearoff=0) self.sinusoidal_menu.add_command(label="Simple Sinusoidal") self.sinusoidal_menu.add_command(label="Two Sinusoidals") self.sinusoidal_menu.add_command(label="More Two Sinusoidals") self.menu_bar.add_cascade(label="Sinusoidal Signals", menu=self.sinusoidal_menu) #Creates a modulation menu self.modulation = tk.Menu(self.menu_bar, tearoff=0) self.modulation.add_command(label="Amplitude Modulation") self.modulation.add_command(label="Frequency Modulation") self.modulation.add_command(label="Phase Modulation") self.menu_bar.add_cascade(label="Modulation", menu=self.modulation) root.config(menu=self.menu_bar) def add_canvas(self, root): #Menambahkan canvas1 widget pada root untuk menampilkan hasil self.figure1 = Figure(figsize=(15.2, 4.2), dpi=100) self.figure1.patch.set_facecolor('gray') self.canvas1 = FigureCanvasTkAgg(self.figure1, master=root) self.canvas1.get_tk_widget().grid(row=0, column=1, columnspan=1, rowspan=25, padx=5, pady=5, sticky="n") #form1.py import tkinter as tk from tkinter import ttk from matplotlib.figure import Figure from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg class Form1: def __init__(self, window): self.window = window width = 1520 height = 760 self.window.geometry(f"{width}x{height}") #Adds canvasses self.add_canvas(self.window) def add_canvas(self, master): # Create a frame for canvas1 with a border frame1 = ttk.Frame(master, borderwidth=3, relief="groove") frame1.grid(row=0, column=0, columnspan=1, rowspan=25, padx=5, pady=5, sticky="n") # Adds canvas1 widget to frame1 self.figure1 = Figure(figsize=(15, 7.4), dpi=100) self.figure1.patch.set_facecolor('#F0F0F0') self.canvas1 = FigureCanvasTkAgg(self.figure1, master=frame1) self.canvas1.get_tk_widget().pack(fill=tk.BOTH, expand=True) if __name__ == "__main__": window = tk.Tk() Form1(window) window.mainloop() #form2.py import tkinter as tk from tkinter import ttk from matplotlib.figure import Figure from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg from signal_utils import Signal_Utils class Form2: def __init__(self, window): self.window = window width = 1520 height = 760 self.window.geometry(f"{width}x{height}") #Adds label widgets self.add_labels(self.window) #Adds entry widgets self.add_entries(self.window) #Adds canvasses self.add_canvas(self.window) #Adds button self.add_button(self.window) self.signal_utils = Signal_Utils() def add_labels(self, master): # Create two labels self.label1 = tk.Label(master, text="START") self.label1.grid(row=0, column=0, padx=5, pady=0.1, sticky="w") self.label2 = tk.Label(master, text="END") self.label2.grid(row=2, column=0, padx=5, pady=0.1, sticky="w") self.label3 = tk.Label(master, text="STEP") self.label3.grid(row=4, column=0, padx=5, pady=0.1, sticky="w") self.label4 = tk.Label(master, text="FREQUENCY 1") self.label4.grid(row=6, column=0, padx=5, pady=0.1, sticky="w") self.label5 = tk.Label(master, text="FREQUENCY 2") self.label5.grid(row=8, column=0, padx=5, pady=0.1, sticky="w") def add_entries(self, master): # Create an entry widget and place it in the first row, first column self.entry_start = tk.Entry(master, width=20, bg="cyan") self.entry_start.grid(row=1, column=0, padx=5, pady=0.1, sticky="n") self.entry_start.insert(0, "0") self.entry_start.bind('<Return>', self.plot_graph_event) # Create an entry widget and place it in the first row, first column self.entry_end = tk.Entry(master, width=20, bg="cyan") self.entry_end.grid(row=3, column=0, padx=5, pady=0.1, sticky="n") self.entry_end.insert(0, "1") self.entry_end.bind('<Return>', self.plot_graph_event) # Create an entry widget and place it in the first row, first column self.entry_step = tk.Entry(master, width=20, bg="cyan") self.entry_step.grid(row=5, column=0, padx=5, pady=0.1, sticky="n") self.entry_step.insert(0, "0.001") self.entry_step.bind('<Return>', self.plot_graph_event) # Create an entry widget and place it in the first row, first column self.entry_freq1 = tk.Entry(master, width=20, bg="cyan") self.entry_freq1.grid(row=7, column=0, padx=5, pady=0.1, sticky="n") self.entry_freq1.insert(0, "7") self.entry_freq1.bind('<Return>', self.plot_graph_event) # Create an entry widget and place it in the first row, first column self.entry_freq2 = tk.Entry(master, width=20, bg="cyan") self.entry_freq2.grid(row=9, column=0, padx=5, pady=0.1, sticky="n") self.entry_freq2.insert(0, "5") self.entry_freq2.bind('<Return>', self.plot_graph_event) def add_canvas(self, master): # Create a frame for canvas1 with a border frame1 = ttk.Frame(master, borderwidth=3, relief="groove") frame1.grid(row=0, column=1, columnspan=1, rowspan=25, padx=5, pady=5, sticky="n") # Adds canvas1 widget to frame1 self.figure1 = Figure(figsize=(13.7, 7.4), dpi=100) self.figure1.patch.set_facecolor('#F0F0F0') self.canvas1 = FigureCanvasTkAgg(self.figure1, master=frame1) self.canvas1.get_tk_widget().pack(fill=tk.BOTH, expand=True) def add_button(self, master): #Adds button self.btn1 = tk.Button(master, height=2, width=17, text="PLOT GRAPH", command=self.plot_graph) self.btn1.grid(row=10, column=0, padx=5, pady=1, sticky="n") def read_and_check_input(self, start, end, step, freq1, freq2): try: start = float(self.entry_start.get()) except ValueError: start = 0 self.entry_start.delete(0, tk.END) self.entry_start.insert(0, "0") try: end = float(self.entry_end.get()) except ValueError: end = 1 self.entry_end.delete(0, tk.END) self.entry_end.insert(0, "1") try: step = float(self.entry_step.get()) except ValueError: step = 0.001 self.entry_step.delete(0, tk.END) self.entry_step.insert(0, "0.001") try: freq1 = float(self.entry_freq1.get()) except ValueError: freq1 = 10 self.entry_freq1.delete(0, tk.END) self.entry_freq1.insert(0, "10") try: freq2 = float(self.entry_freq2.get()) except ValueError: freq2 = 5 self.entry_freq2.delete(0, tk.END) self.entry_freq2.insert(0, "5") return start, end, step, freq1, freq2 def plot_graph(self): start = self.entry_start.get() end = self.entry_end.get() step = self.entry_step.get() freq1 = self.entry_freq1.get() freq2 = self.entry_freq2.get() start, end, step, freq1, freq2 = self.read_and_check_input(start, end, step, freq1, freq2) self.signal_utils.more_two_sines(start, end, step, freq1, freq2, self.figure1, self.canvas1) def plot_graph_event(self, event): self.plot_graph() if __name__ == "__main__": window = tk.Tk() Form2(window) window.mainloop() #signal_utils.py import matplotlib.pyplot as plt import numpy as np class Signal_Utils: def __init__(self): pass def simple_sine(self, figure, canvas): figure.clear() start = 0 end = 1 step = 0.001 x = np.arange(float(start), float(end), float(step)) Fs = 10 y = np.sin(2*np.pi*float(Fs)*x) ax = figure.add_subplot(1,1,1) ax.plot(x, y, linewidth=5.0, color='red') ax.set_ylabel('Amplitude', color='blue') ax.set_xlabel('Time (second)', color='blue') ax.set_title(f'Simple Sinusoidal Graph (Frequency = {Fs} Hz)') ax.set_facecolor('#F0F0F0') ax.grid(True) figure.tight_layout() canvas.draw() def two_sines(self, figure, canvas): figure.clear() start = 0 end = 1 step = 0.001 x = np.arange(float(start), float(end), float(step)) Fs1 = 10 Fs2 = 6 y1 = np.sin(2*np.pi*float(Fs1)*x) y2 = np.cos(2*np.pi*float(Fs2)*x) ax1 = figure.add_subplot(2,2,1) ax1.plot(x, y1, linewidth=3.0, color='red', label=f'Sin(2*pi*{Fs1}*x)') ax1.plot(x, y2, linewidth=3.0, color='black', label=f'Cos(2*pi*{Fs2}*x)') ax1.set_ylabel('Amplitude', color='blue') ax1.set_xlabel('Time (second)', color='blue') ax1.set_title(f'Sin(2*pi*{Fs1}*x) and Cos(2*pi*{Fs2}*x)') ax1.set_facecolor('#F0F0F0') ax1.legend() ax1.grid(True) ax2 = figure.add_subplot(2,2,2) ax2.plot(x, y1*y2, linewidth=3.0, color='green') ax2.set_ylabel('Amplitude', color='blue') ax2.set_xlabel('Time (second)', color='blue') ax2.set_title(f'Sin(2*pi*{Fs1}*x) * Cos(2*pi*{Fs2}*x)') ax2.set_facecolor('#F0F0F0') ax2.grid(True) ax3 = figure.add_subplot(2,2,3) ax3.plot(x, y1 + y2, linewidth=3.0, color='brown') ax3.set_ylabel('Amplitude', color='blue') ax3.set_xlabel('Time (second)', color='blue') ax3.set_title(f'Sin(2*pi*{Fs1}*x) + Cos(2*pi*{Fs2}*x)') ax3.set_facecolor('#F0F0F0') ax3.grid(True) ax4 = figure.add_subplot(2,2,4) ax4.plot(x, y1 - y2, linewidth=3.0, color='blue') ax4.set_ylabel('Amplitude', color='blue') ax4.set_xlabel('Time (second)', color='blue') ax4.set_title(f'Sin(2*pi*{Fs1}*x) - Cos(2*pi*{Fs2}*x)') ax4.set_facecolor('#F0F0F0') ax4.grid(True) figure.tight_layout() canvas.draw() def more_two_sines(self, start=0, end=1, step=0.001, Fs1=7, Fs2=5, figure=None, canvas=None): figure.clear() x = np.arange(float(start), float(end), float(step)) y1 = np.sin(2*np.pi*float(Fs1)*x) y2 = np.cos(2*np.pi*float(Fs2)*x) ax1 = figure.add_subplot(2,2,1) ax1.plot(x, y1, linewidth=3.0, color='red', label=f'Sin(2*pi*{Fs1}*x)') ax1.plot(x, y2, linewidth=3.0, color='black', label=f'Cos(2*pi*{Fs2}*x)') ax1.set_ylabel('Amplitude', color='blue') ax1.set_xlabel('Time (second)', color='blue') ax1.set_title(f'Sin(2*pi*{Fs1}*x) and Cos(2*pi*{Fs2}*x)') ax1.set_facecolor('#F0F0F0') ax1.legend() ax1.grid(True) ax2 = figure.add_subplot(2,2,2) ax2.plot(x, y1*y2, linewidth=3.0, color='green') ax2.set_ylabel('Amplitude', color='blue') ax2.set_xlabel('Time (second)', color='blue') ax2.set_title(f'Sin(2*pi*{Fs1}*x) * Cos(2*pi*{Fs2}*x)') ax2.set_facecolor('#F0F0F0') ax2.grid(True) ax3 = figure.add_subplot(2,2,3) ax3.plot(x, y1 + y2, linewidth=3.0, color='brown') ax3.set_ylabel('Amplitude', color='blue') ax3.set_xlabel('Time (second)', color='blue') ax3.set_title(f'Sin(2*pi*{Fs1}*x) + Cos(2*pi*{Fs2}*x)') ax3.set_facecolor('#F0F0F0') ax3.grid(True) ax4 = figure.add_subplot(2,2,4) ax4.plot(x, y1 - y2, linewidth=3.0, color='blue') ax4.set_ylabel('Amplitude', color='blue') ax4.set_xlabel('Time (second)', color='blue') ax4.set_title(f'Sin(2*pi*{Fs1}*x) - Cos(2*pi*{Fs2}*x)') ax4.set_facecolor('#F0F0F0') ax4.grid(True) figure.tight_layout() canvas.draw() #plot_utils.py import matplotlib.pyplot as plt import tkinter as tk from tkinter import * import seaborn as sns import numpy as np import pandas as pd from form1 import Form1 from form2 import Form2 from form_am import Form_AM from form_fm import Form_FM from form_pm import Form_PM from signal_utils import Signal_Utils class Plot_Utils: def __init__(self): self.signal_utils = Signal_Utils() def plot_simple_sine(self): win = tk.Toplevel() form1 = Form1(win) win.title("Simple Sinusoidal Signal") self.signal_utils.simple_sine(form1.figure1, form1.canvas1) def plot_two_sines(self): win = tk.Toplevel() form1 = Form1(win) win.title("Two Simple Sinusoidal Signals") self.signal_utils.two_sines(form1.figure1, form1.canvas1) def plot_more_two_sines(self): win = tk.Toplevel() win.title("MANIPULATING SINUSOIDAL SIGNALS") form2 = Form2(win) start = float(form2.entry_start.get()) end = float(form2.entry_end.get()) step = float(form2.entry_step.get()) freq1 = float(form2.entry_freq1.get()) freq2 = float(form2.entry_freq2.get()) self.signal_utils.more_two_sines(start, end, step, freq1, freq2, form2.figure1, form2.canvas1) def binds_simple_sinusoidal(self, window): window.sinusoidal_menu.entryconfigure("Simple Sinusoidal", command =lambda:self.plot_simple_sine()) window.sinusoidal_menu.entryconfigure("Two Sinusoidals", command =lambda:self.plot_two_sines()) window.sinusoidal_menu.entryconfigure("More Two Sinusoidals", command =lambda:self.plot_more_two_sines()) def plot_amplitude_modulation(self): win = tk.Toplevel() win.title("AMPLITUDE MODULATION") form_am = Form_AM(win) form_am.plot_fft_am() form_am.plot_graph() def plot_frequency_modulation(self): win = tk.Toplevel() win.title("FREQUENCY MODULATION") form_fm = Form_FM(win) form_fm.plot_fft_fm() form_fm.plot_graph() def plot_phase_modulation(self): win = tk.Toplevel() win.title("PHASE MODULATION") form_pm = Form_PM(win) form_pm.plot_fft_pm() form_pm.plot_graph() def binds_modulation(self, window): window.modulation.entryconfigure("Amplitude Modulation", command =lambda:self.plot_amplitude_modulation()) window.modulation.entryconfigure("Frequency Modulation", command =lambda:self.plot_frequency_modulation()) window.modulation.entryconfigure("Phase Modulation", command =lambda:self.plot_phase_modulation()) #form_am.py import tkinter as tk from tkinter import ttk from matplotlib.figure import Figure from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg from am_utils import AM_Utils from form1 import Form1 class Form_AM: def __init__(self, window): self.window = window width = 1520 height = 760 self.window.geometry(f"{width}x{height}") #Adds label widgets self.add_labels(self.window) #Adds entry widgets self.add_entries(self.window) #Adds canvasses self.add_canvas(self.window) #Adds button self.add_button(self.window) self.am_utils = AM_Utils() def add_labels(self, master): # Create two labels self.label1 = tk.Label(master, text="SAMPLING FREQUENCY") self.label1.grid(row=0, column=0, padx=5, pady=0.1, sticky="w") self.label2 = tk.Label(master, text="TIME PERIODE") self.label2.grid(row=2, column=0, padx=5, pady=0.1, sticky="w") self.label3 = tk.Label(master, text="CARRIER AMPLITUDE") self.label3.grid(row=4, column=0, padx=5, pady=0.1, sticky="w") self.label4 = tk.Label(master, text="CARRIER FREQUENCY") self.label4.grid(row=6, column=0, padx=5, pady=0.1, sticky="w") self.label5 = tk.Label(master, text="MODULATING AMPLITUDE") self.label5.grid(row=8, column=0, padx=5, pady=0.1, sticky="w") self.label6 = tk.Label(master, text="MODULATING FREQUENCY") self.label6.grid(row=10, column=0, padx=5, pady=0.1, sticky="w") self.label7 = tk.Label(master, text="IDX MOD:", font=("Helvetica", 10)) self.label7.grid(row=15, column=0, padx=5, pady=0.1, sticky="w") def add_entries(self, master): # Create entry widgets self.entry_fs = tk.Entry(master, width=20, bg="cyan") self.entry_fs.grid(row=1, column=0, padx=5, pady=0.1, sticky="n") self.entry_fs.insert(0, "1000") self.entry_fs.bind('<Return>', self.plot_graph_event) self.entry_periode = tk.Entry(master, width=20, bg="cyan") self.entry_periode.grid(row=3, column=0, padx=5, pady=0.1, sticky="n") self.entry_periode.insert(0, "1") self.entry_periode.bind('<Return>', self.plot_graph_event) self.entry_ac = tk.Entry(master, width=20, bg="cyan") self.entry_ac.grid(row=5, column=0, padx=5, pady=0.1, sticky="n") self.entry_ac.insert(0, "1") self.entry_ac.bind('<Return>', self.plot_graph_event) self.entry_fc = tk.Entry(master, width=20, bg="cyan") self.entry_fc.grid(row=7, column=0, padx=5, pady=0.1, sticky="n") self.entry_fc.insert(0, "50") self.entry_fc.bind('<Return>', self.plot_graph_event) self.entry_am = tk.Entry(master, width=20, bg="cyan") self.entry_am.grid(row=9, column=0, padx=5, pady=0.1, sticky="n") self.entry_am.insert(0, "1") self.entry_am.bind('<Return>', self.plot_graph_event) self.entry_fm = tk.Entry(master, width=20, bg="cyan") self.entry_fm.grid(row=11, column=0, padx=5, pady=0.1, sticky="n") self.entry_fm.insert(0, "5") self.entry_fm.bind('<Return>', self.plot_graph_event) def add_canvas(self, master): # Create a frame for canvas1 with a border frame1 = ttk.Frame(master, borderwidth=3, relief="groove") frame1.grid(row=0, column=1, columnspan=1, rowspan=25, padx=5, pady=5, sticky="n") # Adds canvas1 widget to frame1 self.figure1 = Figure(figsize=(13.2, 7.4), dpi=100) self.figure1.patch.set_facecolor('#F0F0F0') self.canvas1 = FigureCanvasTkAgg(self.figure1, master=frame1) self.canvas1.get_tk_widget().pack(fill=tk.BOTH, expand=True) def add_button(self, master): #Adds button self.btn1 = tk.Button(master, height=2, width=17, text="PLOT GRAPH", command=self.plot_graph) self.btn1.grid(row=12, column=0, padx=5, pady=1, sticky="n") self.btn2 = tk.Button(master, height=2, width=17, text="PLOT FFT", command=self.plot_fft_am) self.btn2.grid(row=13, column=0, padx=5, pady=1, sticky="n") self.btn3 = tk.Button(master, height=2, width=17, text="PLOT DB", command=self.plot_fft_am_db) self.btn3.grid(row=14, column=0, padx=5, pady=1, sticky="n") def read_and_check_input(self, fs, T, ac, fc, am, fm): try: fsampling = float(fs) except ValueError: fsampling = 1000 self.entry_fs.delete(0, tk.END) self.entry_fs.insert(0, "1000") try: periode = float(T) except ValueError: periode = 1 self.entry_periode.delete(0, tk.END) self.entry_periode.insert(0, "1") try: amp_carrier = float(ac) except ValueError: amp_carrier = 1 self.entry_ac.delete(0, tk.END) self.entry_ac.insert(0, "1") try: freq_carrier = float(fc) except ValueError: freq_carrier = 50 self.entry_fc.delete(0, tk.END) self.entry_fc.insert(0, "50") try: amp_mod = float(am) except ValueError: amp_mod = 1 self.entry_am.delete(0, tk.END) self.entry_am.insert(0, "1") try: freq_mod = float(fm) except ValueError: freq_mod = 5 self.entry_fm.delete(0, tk.END) self.entry_fm.insert(0, "5") return fsampling, periode, amp_carrier, freq_carrier, amp_mod, freq_mod def plot_graph(self): #Reads AM params fsampling = self.entry_fs.get() periode = self.entry_periode.get() amp_carrier = self.entry_ac.get() freq_carrier = self.entry_fc.get() amp_mod = self.entry_am.get() freq_mod = self.entry_fm.get() #Change text in label7 for index modulation miu=float(amp_mod)/float(amp_carrier) self.label7.config(text=f"IDX MOD: {miu:.2f}", font=("Helvetica", 12, "bold")) Fs, T, Ac, Fc, Am, Fm = self.read_and_check_input(fsampling, periode, amp_carrier, freq_carrier, amp_mod, freq_mod) # Performs amplitude modulation t, carrier_wave, modulating_wave, am_signal = self.am_utils.calculate_amplitude_modulation(Fs, T, Ac, Fc, Am, Fm) title1 = f'Carrier Signal, frequency = {Fc}, Amplitude = {Ac}' title2 = f'Modulating Signal, frequency = {Fm}, Amplitude = {Am}' title3 = "Amplitude Modulated Signal" self.am_utils.time_domain(t, carrier_wave, title1, modulating_wave, title2, am_signal, title3, self.figure1, self.canvas1) def plot_graph_event(self, event): self.plot_graph() def plot_fft_am(self): #Plots FFT of signals in form1 win2 = tk.Toplevel() win2.title("AMPLITUDE MODULATION (FREQUENCY-DOMAIN)") form1 = Form1(win2) #Reads AM params fsampling = self.entry_fs.get() periode = self.entry_periode.get() amp_carrier = self.entry_ac.get() freq_carrier = self.entry_fc.get() amp_mod = self.entry_am.get() freq_mod = self.entry_fm.get() Fs, T, Ac, Fc, Am, Fm = self.read_and_check_input(fsampling, periode, amp_carrier, freq_carrier, amp_mod, freq_mod) # Performs amplitude modulation t, carrier_wave, modulating_wave, am_signal = self.am_utils.calculate_amplitude_modulation(Fs, T, Ac, Fc, Am, Fm) self.am_utils.plot_fft_signal(Fs, carrier_wave, \ "FFT of Carrier Signal", modulating_wave, "FFT of Modulating Signal", am_signal, "FFT of AM Signal", form1.figure1, form1.canvas1) def plot_fft_am_db(self): #Plots FFT of signals in form1 win2 = tk.Toplevel() win2.title("AMPLITUDE MODULATION (FREQUENCY-DOMAIN) with DECIBLE MAGNITUDE") form1 = Form1(win2) #Reads AM params fsampling = self.entry_fs.get() periode = self.entry_periode.get() amp_carrier = self.entry_ac.get() freq_carrier = self.entry_fc.get() amp_mod = self.entry_am.get() freq_mod = self.entry_fm.get() Fs, T, Ac, Fc, Am, Fm = self.read_and_check_input(fsampling, periode, amp_carrier, freq_carrier, amp_mod, freq_mod) # Performs amplitude modulation t, carrier_wave, modulating_wave, am_signal = self.am_utils.calculate_amplitude_modulation(Fs, T, Ac, Fc, Am, Fm) self.am_utils.plot_fft_db(Fs, carrier_wave, \ "Decible Magnitude of Carrier Signal", modulating_wave, "Decible Magnitude of Modulating Signal", am_signal, "Decible Magnitude of AM Signal", form1.figure1, form1.canvas1) if __name__ == "__main__": window = tk.Tk() Form_AM(window) window.mainloop() #am_utils.py import matplotlib.pyplot as plt import numpy as np class AM_Utils: def __init__(self): pass def calculate_amplitude_modulation(self, Fs, T, Ac, Fc, Am, Fm): # Define time line t = np.arange(0, T, 1/Fs) # Carrier signal carrier_wave = Ac*np.cos(2*np.pi*Fc*t) # Modulating signal modulating_wave = Am*np.cos(2*np.pi*Fm*t) # Amplitude modulation miu = Am/Ac am_signal = Ac*(1 + miu*np.cos(2*np.pi*Fm*t)) * np.cos(2*np.pi*Fc*t) return t, carrier_wave, modulating_wave, am_signal def time_domain(self, t, carrier_wave, title1, modulating_wave, title2, am_signal, title3, figure=None, canvas=None): figure.clear() ax1 = figure.add_subplot(3,1,1) ax1.plot(t, carrier_wave, linewidth=3.0, color='red') ax1.set_ylabel('Amplitude', color='blue') ax1.set_xlabel('Time (second)', color='blue') ax1.set_title(title1) ax1.set_facecolor('#F0F0F0') ax1.grid(True) ax2 = figure.add_subplot(3,1,2) ax2.plot(t, modulating_wave, linewidth=3.0, color='black') ax2.set_ylabel('Amplitude', color='blue') ax2.set_xlabel('Time (second)', color='blue') ax2.set_title(title2) ax2.set_facecolor('#F0F0F0') ax2.grid(True) ax3 = figure.add_subplot(3,1,3) ax3.plot(t, am_signal, linewidth=3.0, color='blue') ax3.set_ylabel('Amplitude', color='blue') ax3.set_xlabel('Time (second)', color='blue') ax3.set_title(title3) ax3.set_facecolor('#F0F0F0') ax3.grid(True) figure.tight_layout() canvas.draw() def fft_signal(self, Fs, signal): # Perform FFT fft_result = np.fft.fft(signal) freqs = np.fft.fftfreq(len(signal), 1/Fs) # Keep only positive frequencies pos_freqs = freqs[:len(freqs)//2] pos_fft_result = fft_result[:len(fft_result)//2] return pos_freqs, pos_fft_result def fft_db(self, Fs, signal): # Apply Hamming window windowed_signal = signal * np.hamming(len(signal)) # Perform FFT and converts its magnitude to decibel fft_result = np.fft.fft(windowed_signal) # Handle cases where fft_result is zero magnitude_dB = np.zeros_like(fft_result) non_zero_indices = np.abs(fft_result) > 0.01 magnitude_dB[non_zero_indices] = 20*np.log10(np.abs(fft_result[non_zero_indices])) freqs = np.fft.fftfreq(len(signal), 1/Fs) # Keep only positive frequencies pos_freqs = freqs[:len(freqs)//2] pos_magnitude_dB = magnitude_dB[:len(magnitude_dB)//2] return pos_freqs, pos_magnitude_dB def plot_fft_signal(self, Fs, signal1, title1, signal2, title2, signal3, title3, figure=None, canvas=None): figure.clear() #Calculate FFT freqs1, fft_result1 = self.fft_signal(Fs, signal1) freqs2, fft_result2 = self.fft_signal(Fs, signal2) freqs3, fft_result3 = self.fft_signal(Fs, signal3) ax1 = figure.add_subplot(3,1,1) ax1.plot(freqs1, np.abs(fft_result1), linewidth=2.0, color='red') ax1.set_ylabel('Magnitude', color='blue') ax1.set_xlabel('Frequency (Hz)', color='blue') ax1.set_title(title1) ax1.set_xticks(np.arange(min(freqs1), max(freqs1)+1, step=100)) ax1.set_facecolor('#F0F0F0') ax1.grid(True) ax2 = figure.add_subplot(3,1,2) ax2.plot(freqs2, np.abs(fft_result2), linewidth=2.0, color='black') ax2.set_ylabel('Magnitude', color='blue') ax2.set_xlabel('Frequency (Hz)', color='blue') ax2.set_title(title2) ax2.set_facecolor('#F0F0F0') ax2.set_xticks(np.arange(min(freqs1), max(freqs2)+1, step=100)) ax2.grid(True) ax3 = figure.add_subplot(3,1,3) ax3.plot(freqs3, np.abs(fft_result3), linewidth=2.0, color='blue') ax3.set_ylabel('Magnitude', color='blue') ax3.set_xlabel('Frequency (Hz)', color='blue') ax3.set_title(title3) ax3.set_facecolor('#F0F0F0') ax3.set_xticks(np.arange(min(freqs1), max(freqs3)+1, step=100)) ax3.grid(True) figure.tight_layout() canvas.draw() def plot_fft_db(self, Fs, signal1, title1, signal2, title2, signal3, title3, figure=None, canvas=None): figure.clear() #Calculate FFT freqs1, fft_result1 = self.fft_db(Fs, signal1) freqs2, fft_result2 = self.fft_db(Fs, signal2) freqs3, fft_result3 = self.fft_db(Fs, signal3) ax1 = figure.add_subplot(3,1,1) ax1.plot(freqs1, np.abs(fft_result1), linewidth=2.0, color='red') ax1.set_ylabel('Magnitude Spectrum (dB)', color='blue') ax1.set_xlabel('Frequency (Hz)', color='blue') ax1.set_title(title1) ax1.set_xticks(np.arange(min(freqs1), max(freqs1)+1, step=100)) ax1.set_facecolor('#F0F0F0') ax1.grid(True) ax2 = figure.add_subplot(3,1,2) ax2.plot(freqs2, np.abs(fft_result2), linewidth=2.0, color='black') ax2.set_ylabel('Magnitude Spectrum (dB)', color='blue') ax2.set_xlabel('Frequency (Hz)', color='blue') ax2.set_title(title2) ax2.set_facecolor('#F0F0F0') ax2.set_xticks(np.arange(min(freqs1), max(freqs2)+1, step=100)) ax2.grid(True) ax3 = figure.add_subplot(3,1,3) ax3.plot(freqs3, np.abs(fft_result3), linewidth=2.0, color='blue') ax3.set_ylabel('Magnitude Spectrum (dB)', color='blue') ax3.set_xlabel('Frequency (Hz)', color='blue') ax3.set_title(title3) ax3.set_facecolor('#F0F0F0') ax3.set_xticks(np.arange(min(freqs1), max(freqs3)+1, step=100)) ax3.grid(True) figure.tight_layout() canvas.draw() #fm_utils.py import matplotlib.pyplot as plt import numpy as np class FM_Utils: def __init__(self): pass def calculate_frequency_modulation(self, beta, Fs, T, Ac, Fc, Am, Fm): # Defines time line t = np.arange(0, T, 1/Fs) # Carrier signal carrier_wave = Ac*np.sin(2*np.pi*Fc*t) # Modulating signal modulating_wave = Am*np.sin(2*np.pi*Fm*t) # Frequency modulation #beta is modulation index fm_signal = Ac*np.sin(2*np.pi*Fc*t + beta*modulating_wave) return t, carrier_wave, modulating_wave, fm_signal #form_fm.py import tkinter as tk from tkinter import ttk from matplotlib.figure import Figure from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg from am_utils import AM_Utils from fm_utils import FM_Utils from form1 import Form1 class Form_FM: def __init__(self, window): self.window = window width = 1520 height = 760 self.window.geometry(f"{width}x{height}") #Adds label widgets self.add_labels(self.window) #Adds entry widgets self.add_entries(self.window) #Adds canvasses self.add_canvas(self.window) #Adds button self.add_button(self.window) #Creates neccesary objects self.am_utils = AM_Utils() self.fm_utils = FM_Utils() def add_labels(self, master): # Create two labels self.label1 = tk.Label(master, text="SAMPLING FREQUENCY") self.label1.grid(row=0, column=0, padx=5, pady=0.1, sticky="w") self.label2 = tk.Label(master, text="TIME PERIODE") self.label2.grid(row=2, column=0, padx=5, pady=0.1, sticky="w") self.label3 = tk.Label(master, text="CARRIER AMPLITUDE") self.label3.grid(row=4, column=0, padx=5, pady=0.1, sticky="w") self.label4 = tk.Label(master, text="CARRIER FREQUENCY") self.label4.grid(row=6, column=0, padx=5, pady=0.1, sticky="w") self.label5 = tk.Label(master, text="MODULATING AMPLITUDE") self.label5.grid(row=8, column=0, padx=5, pady=0.1, sticky="w") self.label6 = tk.Label(master, text="MODULATING FREQUENCY") self.label6.grid(row=10, column=0, padx=5, pady=0.1, sticky="w") self.label7 = tk.Label(master, text="IDX MODULATION:") self.label7.grid(row=12, column=0, padx=5, pady=0.1, sticky="w") def add_entries(self, master): # Create entry widgets self.entry_fs = tk.Entry(master, width=20, bg="cyan") self.entry_fs.grid(row=1, column=0, padx=5, pady=0.1, sticky="n") self.entry_fs.insert(0, "1000") self.entry_fs.bind('<Return>', self.plot_graph_event) self.entry_periode = tk.Entry(master, width=20, bg="cyan") self.entry_periode.grid(row=3, column=0, padx=5, pady=0.1, sticky="n") self.entry_periode.insert(0, "1") self.entry_periode.bind('<Return>', self.plot_graph_event) self.entry_ac = tk.Entry(master, width=20, bg="cyan") self.entry_ac.grid(row=5, column=0, padx=5, pady=0.1, sticky="n") self.entry_ac.insert(0, "1") self.entry_ac.bind('<Return>', self.plot_graph_event) self.entry_fc = tk.Entry(master, width=20, bg="cyan") self.entry_fc.grid(row=7, column=0, padx=5, pady=0.1, sticky="n") self.entry_fc.insert(0, "50") self.entry_fc.bind('<Return>', self.plot_graph_event) self.entry_am = tk.Entry(master, width=20, bg="cyan") self.entry_am.grid(row=9, column=0, padx=5, pady=0.1, sticky="n") self.entry_am.insert(0, "1") self.entry_am.bind('<Return>', self.plot_graph_event) self.entry_fm = tk.Entry(master, width=20, bg="cyan") self.entry_fm.grid(row=11, column=0, padx=5, pady=0.1, sticky="n") self.entry_fm.insert(0, "5") self.entry_fm.bind('<Return>', self.plot_graph_event) self.entry_idx_mod = tk.Entry(master, width=20, bg="cyan") self.entry_idx_mod.grid(row=13, column=0, padx=5, pady=0.1, sticky="n") self.entry_idx_mod.insert(0, "5") self.entry_idx_mod.bind('<Return>', self.plot_graph_event) def add_canvas(self, master): # Create a frame for canvas1 with a border frame1 = ttk.Frame(master, borderwidth=3, relief="groove") frame1.grid(row=0, column=1, columnspan=1, rowspan=25, padx=5, pady=5, sticky="n") # Adds canvas1 widget to frame1 self.figure1 = Figure(figsize=(13.2, 7.4), dpi=100) self.figure1.patch.set_facecolor('#F0F0F0') self.canvas1 = FigureCanvasTkAgg(self.figure1, master=frame1) self.canvas1.get_tk_widget().pack(fill=tk.BOTH, expand=True) def add_button(self, master): #Adds button self.btn1 = tk.Button(master, height=2, width=17, text="PLOT GRAPH", command=self.plot_graph) self.btn1.grid(row=14, column=0, padx=5, pady=1, sticky="n") self.btn2 = tk.Button(master, height=2, width=17, text="PLOT FFT", command=self.plot_fft_fm) self.btn2.grid(row=15, column=0, padx=5, pady=1, sticky="n") self.btn3 = tk.Button(master, height=2, width=17, text="PLOT DB", command=self.plot_fft_fm_db) self.btn3.grid(row=16, column=0, padx=5, pady=1, sticky="n") def read_and_check_input(self, beta, fs, T, ac, fc, am, fm): try: idx_mod = float(beta) except ValueError: idx_mod = 5 self.entry_idx_mod.delete(0, tk.END) self.entry_idx_mod.insert(0, "5") try: fsampling = float(fs) except ValueError: fsampling = 1000 self.entry_fs.delete(0, tk.END) self.entry_fs.insert(0, "1000") try: periode = float(T) except ValueError: periode = 1 self.entry_periode.delete(0, tk.END) self.entry_periode.insert(0, "1") try: amp_carrier = float(ac) except ValueError: amp_carrier = 1 self.entry_ac.delete(0, tk.END) self.entry_ac.insert(0, "1") try: freq_carrier = float(fc) except ValueError: freq_carrier = 50 self.entry_fc.delete(0, tk.END) self.entry_fc.insert(0, "50") try: amp_mod = float(am) except ValueError: amp_mod = 1 self.entry_am.delete(0, tk.END) self.entry_am.insert(0, "1") try: freq_mod = float(fm) except ValueError: freq_mod = 5 self.entry_fm.delete(0, tk.END) self.entry_fm.insert(0, "5") return idx_mod, fsampling, periode, amp_carrier, freq_carrier, amp_mod, freq_mod def plot_graph(self): #Reads FM params idx_mod = self.entry_idx_mod.get() fsampling = self.entry_fs.get() periode = self.entry_periode.get() amp_carrier = self.entry_ac.get() freq_carrier = self.entry_fc.get() amp_mod = self.entry_am.get() freq_mod = self.entry_fm.get() beta, Fs, T, Ac, Fc, Am, Fm = self.read_and_check_input(idx_mod, fsampling, periode, amp_carrier, freq_carrier, amp_mod, freq_mod) # Performs frequency modulation t, carrier_wave, modulating_wave, fm_signal = self.fm_utils.calculate_frequency_modulation(beta, Fs, T, Ac, Fc, Am, Fm) title1 = f'Carrier Signal, frequency = {Fc}, Amplitude = {Ac}' title2 = f'Modulating Signal, frequency = {Fm}, Amplitude = {Am}' title3 = "Frequency Modulated Signal" self.am_utils.time_domain(t, carrier_wave, title1, modulating_wave, title2, fm_signal, title3, self.figure1, self.canvas1) def plot_graph_event(self, event): self.plot_graph() def plot_fft_fm(self): #Plots FFT of signals in form1 win2 = tk.Toplevel() win2.title("FREQUENCY MODULATION (FREQUENCY-DOMAIN)") form1 = Form1(win2) #Reads FM params idx_mod = self.entry_idx_mod.get() fsampling = self.entry_fs.get() periode = self.entry_periode.get() amp_carrier = self.entry_ac.get() freq_carrier = self.entry_fc.get() amp_mod = self.entry_am.get() freq_mod = self.entry_fm.get() beta, Fs, T, Ac, Fc, Am, Fm = self.read_and_check_input(idx_mod, fsampling, periode, amp_carrier, freq_carrier, amp_mod, freq_mod) # Performs frequency modulation t, carrier_wave, modulating_wave, fm_signal = self.fm_utils.calculate_frequency_modulation(beta, Fs, T, Ac, Fc, Am, Fm) self.am_utils.plot_fft_signal(Fs, carrier_wave, \ "FFT of Carrier Signal", modulating_wave, "FFT of Modulating Signal", fm_signal, "FFT of FM Signal", form1.figure1, form1.canvas1) def plot_fft_fm_db(self): #Plots FFT of signals in form1 win2 = tk.Toplevel() win2.title("FREQUENCY MODULATION (FREQUENCY-DOMAIN) with DECIBLE MAGNITUDE") form1 = Form1(win2) #Reads FM params idx_mod = self.entry_idx_mod.get() fsampling = self.entry_fs.get() periode = self.entry_periode.get() amp_carrier = self.entry_ac.get() freq_carrier = self.entry_fc.get() amp_mod = self.entry_am.get() freq_mod = self.entry_fm.get() beta, Fs, T, Ac, Fc, Am, Fm = self.read_and_check_input(idx_mod, fsampling, periode, amp_carrier, freq_carrier, amp_mod, freq_mod) # Performs frequency modulation t, carrier_wave, modulating_wave, fm_signal = self.fm_utils.calculate_frequency_modulation(beta, Fs, T, Ac, Fc, Am, Fm) self.am_utils.plot_fft_db(Fs, carrier_wave, \ "Decible Magnitude of Carrier Signal", modulating_wave, "Decible Magnitude of Modulating Signal", fm_signal, "Decible Magnitude of FM Signal", form1.figure1, form1.canvas1) if __name__ == "__main__": window = tk.Tk() Form_FM(window) window.mainloop() #pm_utils.py import matplotlib.pyplot as plt import numpy as np class PM_Utils: def __init__(self): pass def calculate_phase_modulation(self, Fs, T, Ac, Fc, phi_c, Am, Fm, phi_m): # Defines time line t = np.arange(0, T, 1/Fs) # Carrier signal carrier_wave = Ac*np.sin(2*np.pi*Fc*t+ phi_c) # Modulating signal modulating_wave = Am*np.sin(2*np.pi*Fm*t + phi_m) # Phase modulation pm_signal = Ac*np.sin(Fc*2*np.pi*t + phi_c + Am*np.sin(Fm*2*np.pi*t+phi_m)) return t, carrier_wave, modulating_wave, pm_signal #form_pm.py import tkinter as tk from tkinter import ttk from matplotlib.figure import Figure from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg from am_utils import AM_Utils from pm_utils import PM_Utils from form1 import Form1 class Form_PM: def __init__(self, window): self.window = window width = 1520 height = 760 self.window.geometry(f"{width}x{height}") #Adds label widgets self.add_labels(self.window) #Adds entry widgets self.add_entries(self.window) #Adds canvasses self.add_canvas(self.window) #Adds button self.add_button(self.window) #Creates neccesary objects self.am_utils = AM_Utils() self.pm_utils = PM_Utils() def add_labels(self, master): # Create two labels self.label1 = tk.Label(master, text="SAMPLING FREQUENCY") self.label1.grid(row=0, column=0, padx=5, pady=0.1, sticky="w") self.label2 = tk.Label(master, text="TIME PERIODE") self.label2.grid(row=2, column=0, padx=5, pady=0.1, sticky="w") self.label3 = tk.Label(master, text="CARRIER AMPLITUDE") self.label3.grid(row=4, column=0, padx=5, pady=0.1, sticky="w") self.label4 = tk.Label(master, text="CARRIER FREQUENCY") self.label4.grid(row=6, column=0, padx=5, pady=0.1, sticky="w") self.label5 = tk.Label(master, text="CARRIER PHASE") self.label5.grid(row=8, column=0, padx=5, pady=0.1, sticky="w") self.label5 = tk.Label(master, text="MODULATING AMPLITUDE") self.label5.grid(row=10, column=0, padx=5, pady=0.1, sticky="w") self.label6 = tk.Label(master, text="MODULATING FREQUENCY") self.label6.grid(row=12, column=0, padx=5, pady=0.1, sticky="w") self.label7 = tk.Label(master, text="MODULATING PHASE:") self.label7.grid(row=14, column=0, padx=5, pady=0.1, sticky="w") def add_entries(self, master): # Create entry widgets self.entry_fs = tk.Entry(master, width=20, bg="cyan") self.entry_fs.grid(row=1, column=0, padx=5, pady=0.1, sticky="n") self.entry_fs.insert(0, "1000") self.entry_fs.bind('<Return>', self.plot_graph_event) self.entry_periode = tk.Entry(master, width=20, bg="cyan") self.entry_periode.grid(row=3, column=0, padx=5, pady=0.1, sticky="n") self.entry_periode.insert(0, "1") self.entry_periode.bind('<Return>', self.plot_graph_event) self.entry_ac = tk.Entry(master, width=20, bg="cyan") self.entry_ac.grid(row=5, column=0, padx=5, pady=0.1, sticky="n") self.entry_ac.insert(0, "1") self.entry_ac.bind('<Return>', self.plot_graph_event) self.entry_fc = tk.Entry(master, width=20, bg="cyan") self.entry_fc.grid(row=7, column=0, padx=5, pady=0.1, sticky="n") self.entry_fc.insert(0, "50") self.entry_fc.bind('<Return>', self.plot_graph_event) self.entry_pc = tk.Entry(master, width=20, bg="cyan") self.entry_pc.grid(row=9, column=0, padx=5, pady=0.1, sticky="n") self.entry_pc.insert(0, "0") self.entry_pc.bind('<Return>', self.plot_graph_event) self.entry_am = tk.Entry(master, width=20, bg="cyan") self.entry_am.grid(row=11, column=0, padx=5, pady=0.1, sticky="n") self.entry_am.insert(0, "1") self.entry_am.bind('<Return>', self.plot_graph_event) self.entry_fm = tk.Entry(master, width=20, bg="cyan") self.entry_fm.grid(row=13, column=0, padx=5, pady=0.1, sticky="n") self.entry_fm.insert(0, "5") self.entry_fm.bind('<Return>', self.plot_graph_event) self.entry_pm = tk.Entry(master, width=20, bg="cyan") self.entry_pm.grid(row=15, column=0, padx=5, pady=0.1, sticky="n") self.entry_pm.insert(0, "0") self.entry_pm.bind('<Return>', self.plot_graph_event) def add_canvas(self, master): # Create a frame for canvas1 with a border frame1 = ttk.Frame(master, borderwidth=3, relief="groove") frame1.grid(row=0, column=1, columnspan=1, rowspan=25, padx=5, pady=5, sticky="n") # Adds canvas1 widget to frame1 self.figure1 = Figure(figsize=(13.2, 7.4), dpi=100) self.figure1.patch.set_facecolor('#F0F0F0') self.canvas1 = FigureCanvasTkAgg(self.figure1, master=frame1) self.canvas1.get_tk_widget().pack(fill=tk.BOTH, expand=True) def add_button(self, master): #Adds button self.btn1 = tk.Button(master, height=2, width=17, text="PLOT GRAPH", command=self.plot_graph) self.btn1.grid(row=16, column=0, padx=5, pady=1, sticky="n") self.btn2 = tk.Button(master, height=2, width=17, text="PLOT FFT", command=self.plot_fft_pm) self.btn2.grid(row=17, column=0, padx=5, pady=1, sticky="n") self.btn3 = tk.Button(master, height=2, width=17, text="PLOT DB", command=self.plot_fft_pm_db) self.btn3.grid(row=18, column=0, padx=5, pady=1, sticky="n") def read_and_check_input(self, fs, T, ac, fc, pc, am, fm, pm): try: fsampling = float(fs) except ValueError: fsampling = 1000 self.entry_fs.delete(0, tk.END) self.entry_fs.insert(0, "1000") try: periode = float(T) except ValueError: periode = 1 self.entry_periode.delete(0, tk.END) self.entry_periode.insert(0, "1") try: amp_carrier = float(ac) except ValueError: amp_carrier = 1 self.entry_ac.delete(0, tk.END) self.entry_ac.insert(0, "1") try: freq_carrier = float(fc) except ValueError: freq_carrier = 50 self.entry_fc.delete(0, tk.END) self.entry_fc.insert(0, "50") try: phi_c = float(pc) except ValueError: phi_c = 0 self.entry_pc.delete(0, tk.END) self.entry_pc.insert(0, "0") try: amp_mod = float(am) except ValueError: amp_mod = 1 self.entry_am.delete(0, tk.END) self.entry_am.insert(0, "1") try: freq_mod = float(fm) except ValueError: freq_mod = 5 self.entry_fm.delete(0, tk.END) self.entry_fm.insert(0, "5") try: phi_m = float(pm) except ValueError: phi_m = 0 self.entry_pm.delete(0, tk.END) self.entry_pm.insert(0, "0") return fsampling, periode, amp_carrier, freq_carrier, phi_c, amp_mod, freq_mod, phi_m def plot_graph(self): #Reads PM params fsampling = self.entry_fs.get() periode = self.entry_periode.get() amp_carrier = self.entry_ac.get() freq_carrier = self.entry_fc.get() phase_carrier = self.entry_pc.get() amp_mod = self.entry_am.get() freq_mod = self.entry_fm.get() phase_mod = self.entry_pm.get() Fs, T, Ac, Fc, phi_c, Am, Fm, phi_m = self.read_and_check_input(fsampling, periode, amp_carrier, freq_carrier, phase_carrier, amp_mod, freq_mod, phase_mod) # Performs phase modulation t, carrier_wave, modulating_wave, fm_signal = \ self.pm_utils.calculate_phase_modulation(Fs, T, Ac, Fc, phi_c, Am, Fm, phi_m) title1 = f'Carrier Signal, frequency = {Fc}, Amplitude = {Ac}, Phase = {phi_c}' title2 = f'Modulating Signal, frequency = {Fm}, Amplitude = {Am}, Phase = {phi_m}' title3 = "Phase Modulated Signal" self.am_utils.time_domain(t, carrier_wave, title1, modulating_wave, title2, fm_signal, title3, self.figure1, self.canvas1) def plot_graph_event(self, event): self.plot_graph() def plot_fft_pm(self): #Plots FFT of signals in form1 win2 = tk.Toplevel() win2.title("PHASE MODULATION (FREQUENCY-DOMAIN)") form1 = Form1(win2) #Reads PM params fsampling = self.entry_fs.get() periode = self.entry_periode.get() amp_carrier = self.entry_ac.get() freq_carrier = self.entry_fc.get() phase_carrier = self.entry_pc.get() amp_mod = self.entry_am.get() freq_mod = self.entry_fm.get() phase_mod = self.entry_pm.get() Fs, T, Ac, Fc, phi_c, Am, Fm, phi_m = self.read_and_check_input(fsampling, periode, amp_carrier, freq_carrier, phase_carrier, amp_mod, freq_mod, phase_mod) # Performs phase modulation t, carrier_wave, modulating_wave, pm_signal = \ self.pm_utils.calculate_phase_modulation(Fs, T, Ac, Fc, phi_c, Am, Fm, phi_m) self.am_utils.plot_fft_signal(Fs, carrier_wave, \ "FFT of Carrier Signal", modulating_wave, "FFT of Modulating Signal", pm_signal, "FFT of Phase-Modulated Signal", form1.figure1, form1.canvas1) def plot_fft_pm_db(self): #Plots FFT of signals in form1 win2 = tk.Toplevel() win2.title("PHASE MODULATION (FREQUENCY-DOMAIN) with DECIBLE MAGNITUDE") form1 = Form1(win2) #Reads PM params fsampling = self.entry_fs.get() periode = self.entry_periode.get() amp_carrier = self.entry_ac.get() freq_carrier = self.entry_fc.get() phase_carrier = self.entry_pc.get() amp_mod = self.entry_am.get() freq_mod = self.entry_fm.get() phase_mod = self.entry_pm.get() Fs, T, Ac, Fc, phi_c, Am, Fm, phi_m = self.read_and_check_input(fsampling, periode, amp_carrier, freq_carrier, phase_carrier, amp_mod, freq_mod, phase_mod) # Performs phase modulation t, carrier_wave, modulating_wave, pm_signal = \ self.pm_utils.calculate_phase_modulation(Fs, T, Ac, Fc, phi_c, Am, Fm, phi_m) self.am_utils.plot_fft_db(Fs, carrier_wave, \ "Decible Magnitude of Carrier Signal", modulating_wave, "Decible Magnitude of Modulating Signal", pm_signal, "Decible Magnitude of Phase-Modulated Signal", form1.figure1, form1.canvas1) if __name__ == "__main__": window = tk.Tk() Form_PM(window) window.mainloop()
FULL SOURCE CODE 6.0: AMPLITUDE-SHIFT KEYING (ASK) MODULATION
FULL SOURCE CODE 7.0: FREQUENCY-SHIFT KEYING (FSK) MODULATION
#fsk_utils.py import matplotlib.pyplot as plt import numpy as np class FSK_Utils: def __init__(self): pass def generate_random_binary_array(self, length): # Generate a random binary array of specified length return np.random.randint(2, size=length) def calculate_fsk_modulation(self, Fs, T, Ac, Fc, phi_c, samples_per_bit): # Defines time line t = np.arange(0, T, 1/Fs) bit_arr_size = int(2*Fs/samples_per_bit) bit_arr = self.generate_random_binary_array(bit_arr_size) modulating_wave = np.repeat(bit_arr, samples_per_bit)[:len(t)] # Ensures the lengths of modulating_wave and t match if len(modulating_wave) < len(t): modulating_wave = np.pad(modulating_wave, (0, len(t) - len(modulating_wave))) # Carrier signal carrier_wave = Ac*np.sin(2*np.pi*Fc*t+ phi_c) #Frequency-shift keying modulated signal freq_sk = Fc*(1 + modulating_wave) fsk_signal = Ac*np.sin(2*np.pi*freq_sk*t+ phi_c) return t, carrier_wave, modulating_wave, fsk_signal #form_fsk.py import tkinter as tk from tkinter import ttk from matplotlib.figure import Figure from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg from am_utils import AM_Utils from fsk_utils import FSK_Utils from form1 import Form1 class Form_FSK: def __init__(self, window): self.window = window width = 1520 height = 760 self.window.geometry(f"{width}x{height}") #Adds label widgets self.add_labels(self.window) #Adds entry widgets self.add_entries(self.window) #Adds canvasses self.add_canvas(self.window) #Adds button self.add_button(self.window) #Creates neccesary objects self.am_utils = AM_Utils() self.fsk_utils = FSK_Utils() def add_labels(self, master): # Create two labels self.label1 = tk.Label(master, text="SAMPLING FREQUENCY") self.label1.grid(row=0, column=0, padx=5, pady=0.1, sticky="w") self.label2 = tk.Label(master, text="TIME PERIODE") self.label2.grid(row=2, column=0, padx=5, pady=0.1, sticky="w") self.label3 = tk.Label(master, text="CARRIER AMPLITUDE") self.label3.grid(row=4, column=0, padx=5, pady=0.1, sticky="w") self.label4 = tk.Label(master, text="CARRIER FREQUENCY") self.label4.grid(row=6, column=0, padx=5, pady=0.1, sticky="w") self.label5 = tk.Label(master, text="CARRIER PHASE") self.label5.grid(row=8, column=0, padx=5, pady=0.1, sticky="w") self.label5 = tk.Label(master, text="SAMPLES PER BIT") self.label5.grid(row=10, column=0, padx=5, pady=0.1, sticky="w") def add_entries(self, master): # Create entry widgets self.entry_fs = tk.Entry(master, width=20, bg="lightblue") self.entry_fs.grid(row=1, column=0, padx=5, pady=0.1, sticky="n") self.entry_fs.insert(0, "1000") self.entry_fs.bind('<Return>', self.plot_graph_event) self.entry_periode = tk.Entry(master, width=20, bg="lightblue") self.entry_periode.grid(row=3, column=0, padx=5, pady=0.1, sticky="n") self.entry_periode.insert(0, "1") self.entry_periode.bind('<Return>', self.plot_graph_event) self.entry_ac = tk.Entry(master, width=20, bg="lightblue") self.entry_ac.grid(row=5, column=0, padx=5, pady=0.1, sticky="n") self.entry_ac.insert(0, "1") self.entry_ac.bind('<Return>', self.plot_graph_event) self.entry_fc = tk.Entry(master, width=20, bg="lightblue") self.entry_fc.grid(row=7, column=0, padx=5, pady=0.1, sticky="n") self.entry_fc.insert(0, "50") self.entry_fc.bind('<Return>', self.plot_graph_event) self.entry_pc = tk.Entry(master, width=20, bg="lightblue") self.entry_pc.grid(row=9, column=0, padx=5, pady=0.1, sticky="n") self.entry_pc.insert(0, "0") self.entry_pc.bind('<Return>', self.plot_graph_event) self.entry_spb = tk.Entry(master, width=20, bg="lightblue") self.entry_spb.grid(row=11, column=0, padx=5, pady=0.1, sticky="n") self.entry_spb.insert(0, "50") self.entry_spb.bind('<Return>', self.plot_graph_event) def add_canvas(self, master): # Create a frame for canvas1 with a border frame1 = ttk.Frame(master, borderwidth=3, relief="groove") frame1.grid(row=0, column=1, columnspan=1, rowspan=25, padx=5, pady=5, sticky="n") # Adds canvas1 widget to frame1 self.figure1 = Figure(figsize=(13.2, 7.4), dpi=100) self.figure1.patch.set_facecolor('#F0F0F0') self.canvas1 = FigureCanvasTkAgg(self.figure1, master=frame1) self.canvas1.get_tk_widget().pack(fill=tk.BOTH, expand=True) def add_button(self, master): #Adds button self.btn1 = tk.Button(master, height=2, width=17, text="PLOT GRAPH", command=self.plot_graph) self.btn1.grid(row=12, column=0, padx=5, pady=1, sticky="n") self.btn2 = tk.Button(master, height=2, width=17, text="PLOT FFT", command=self.plot_fft_fsk) self.btn2.grid(row=13, column=0, padx=5, pady=1, sticky="n") self.btn3 = tk.Button(master, height=2, width=17, text="PLOT DB", command=self.plot_fft_fsk_db) self.btn3.grid(row=14, column=0, padx=5, pady=1, sticky="n") def read_and_check_input(self, fs, T, ac, fc, pc, N): try: fsampling = float(fs) except ValueError: fsampling = 1000 self.entry_fs.delete(0, tk.END) self.entry_fs.insert(0, "1000") try: periode = float(T) except ValueError: periode = 1 self.entry_periode.delete(0, tk.END) self.entry_periode.insert(0, "1") try: amp_carrier = float(ac) except ValueError: amp_carrier = 1 self.entry_ac.delete(0, tk.END) self.entry_ac.insert(0, "1") try: freq_carrier = float(fc) except ValueError: freq_carrier = 50 self.entry_fc.delete(0, tk.END) self.entry_fc.insert(0, "50") try: phi_c = float(pc) except ValueError: phi_c = 0 self.entry_pc.delete(0, tk.END) self.entry_pc.insert(0, "0") try: spb = int(N) except ValueError: spb = 50 self.entry_length.delete(0, tk.END) self.entry_length.insert(0, "50") return fsampling, periode, amp_carrier, freq_carrier, phi_c, spb def plot_graph(self): #Reads FSK params fsampling = self.entry_fs.get() periode = self.entry_periode.get() amp_carrier = self.entry_ac.get() freq_carrier = self.entry_fc.get() phase_carrier = self.entry_pc.get() spb = self.entry_spb.get() Fs, T, Ac, Fc, phi_c, samples_per_bit = self.read_and_check_input(fsampling, periode, amp_carrier, freq_carrier, phase_carrier, spb) # Performs FSK modulation t, carrier_wave, modulating_wave, ask_signal = \ self.fsk_utils.calculate_fsk_modulation(Fs, T, Ac, Fc, phi_c, samples_per_bit) title1 = f'Carrier Signal, frequency = {Fc}, Amplitude = {Ac}, Phase = {phi_c}' title2 = f'Modulating Signal, samples per bit = {samples_per_bit}' title3 = "FSK Modulated Signal" self.am_utils.time_domain(t, carrier_wave, title1, modulating_wave, title2, ask_signal, title3, self.figure1, self.canvas1) def plot_graph_event(self, event): self.plot_graph() def plot_fft_fsk(self): #Plots FFT of signals in form1 win2 = tk.Toplevel() win2.title("FSK MODULATION (FREQUENCY-DOMAIN)") form1 = Form1(win2) #Reads FSK params fsampling = self.entry_fs.get() periode = self.entry_periode.get() amp_carrier = self.entry_ac.get() freq_carrier = self.entry_fc.get() phase_carrier = self.entry_pc.get() spb = self.entry_spb.get() Fs, T, Ac, Fc, phi_c, samples_per_bit = self.read_and_check_input(fsampling, periode, amp_carrier, freq_carrier, phase_carrier, spb) # Performs FSK modulation t, carrier_wave, modulating_wave, ask_signal = \ self.fsk_utils.calculate_fsk_modulation(Fs, T, Ac, Fc, phi_c, samples_per_bit) self.am_utils.plot_fft_signal(Fs, carrier_wave, \ "FFT of Carrier Signal", modulating_wave, "FFT of Modulating Signal", ask_signal, "FFT of ASK-Modulated Signal", form1.figure1, form1.canvas1) def plot_fft_fsk_db(self): #Plots FFT of signals in form1 win2 = tk.Toplevel() win2.title("FSK MODULATION (FREQUENCY-DOMAIN) with DECIBLE MAGNITUDE") form1 = Form1(win2) #Reads FSK params fsampling = self.entry_fs.get() periode = self.entry_periode.get() amp_carrier = self.entry_ac.get() freq_carrier = self.entry_fc.get() phase_carrier = self.entry_pc.get() spb = self.entry_spb.get() Fs, T, Ac, Fc, phi_c, samples_per_bit = self.read_and_check_input(fsampling, periode, amp_carrier, freq_carrier, phase_carrier, spb) # Performs FSK modulation t, carrier_wave, modulating_wave, ask_signal = \ self.fsk_utils.calculate_fsk_modulation(Fs, T, Ac, Fc, phi_c, samples_per_bit) self.am_utils.plot_fft_db(Fs, carrier_wave, \ "Decible Magnitude of Carrier Signal", modulating_wave, "Decible Magnitude of Modulating Signal", ask_signal, "Decible Magnitude of ASK-Modulated Signal", form1.figure1, form1.canvas1) if __name__ == "__main__": window = tk.Tk() Form_FSK(window) window.mainloop()
DOWNLOAD FULL SOURCE CODE VERSION 7.0
FULL SOURCE CODE 8.0: PHASE-SHIFT KEYING (PSK) MODULATION
#psk_utils.py import matplotlib.pyplot as plt import numpy as np class PSK_Utils: def __init__(self): pass def generate_random_binary_array(self, length): # Generate a random binary array of specified length return np.random.randint(2, size=length) def calculate_psk_modulation(self, Fs, T, Ac, Fc, phi_c, samples_per_bit): # Defines time line t = np.arange(0, T, 1/Fs) bit_arr_size = int(2*Fs/samples_per_bit) bit_arr = self.generate_random_binary_array(bit_arr_size) modulating_wave = np.repeat(bit_arr, samples_per_bit)[:len(t)] # Ensures the lengths of modulating_wave and t match if len(modulating_wave) < len(t): modulating_wave = np.pad(modulating_wave, (0, len(t) - len(modulating_wave))) # Carrier signal carrier_wave = Ac*np.sin(2*np.pi*Fc*t+ phi_c) #Phase-shift keying modulated signal #Shifts 180 degree psk_signal = Ac * np.sin(2*np.pi*Fc*t + phi_c + np.pi * modulating_wave) return t, carrier_wave, modulating_wave, psk_signal #form_psk.py import tkinter as tk from tkinter import ttk from matplotlib.figure import Figure from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg from am_utils import AM_Utils from psk_utils import PSK_Utils from form1 import Form1 class Form_PSK: def __init__(self, window): self.window = window width = 1520 height = 760 self.window.geometry(f"{width}x{height}") #Adds label widgets self.add_labels(self.window) #Adds entry widgets self.add_entries(self.window) #Adds canvasses self.add_canvas(self.window) #Adds button self.add_button(self.window) #Creates neccesary objects self.am_utils = AM_Utils() self.psk_utils = PSK_Utils() def add_labels(self, master): # Create two labels self.label1 = tk.Label(master, text="SAMPLING FREQUENCY") self.label1.grid(row=0, column=0, padx=5, pady=0.1, sticky="w") self.label2 = tk.Label(master, text="TIME PERIODE") self.label2.grid(row=2, column=0, padx=5, pady=0.1, sticky="w") self.label3 = tk.Label(master, text="CARRIER AMPLITUDE") self.label3.grid(row=4, column=0, padx=5, pady=0.1, sticky="w") self.label4 = tk.Label(master, text="CARRIER FREQUENCY") self.label4.grid(row=6, column=0, padx=5, pady=0.1, sticky="w") self.label5 = tk.Label(master, text="CARRIER PHASE") self.label5.grid(row=8, column=0, padx=5, pady=0.1, sticky="w") self.label6 = tk.Label(master, text="SAMPLES PER BIT") self.label6.grid(row=10, column=0, padx=5, pady=0.1, sticky="w") def add_entries(self, master): # Create entry widgets self.entry_fs = tk.Entry(master, width=20, bg="lightblue") self.entry_fs.grid(row=1, column=0, padx=5, pady=0.1, sticky="n") self.entry_fs.insert(0, "1000") self.entry_fs.bind('<Return>', self.plot_graph_event) self.entry_periode = tk.Entry(master, width=20, bg="lightblue") self.entry_periode.grid(row=3, column=0, padx=5, pady=0.1, sticky="n") self.entry_periode.insert(0, "1") self.entry_periode.bind('<Return>', self.plot_graph_event) self.entry_ac = tk.Entry(master, width=20, bg="lightblue") self.entry_ac.grid(row=5, column=0, padx=5, pady=0.1, sticky="n") self.entry_ac.insert(0, "1") self.entry_ac.bind('<Return>', self.plot_graph_event) self.entry_fc = tk.Entry(master, width=20, bg="lightblue") self.entry_fc.grid(row=7, column=0, padx=5, pady=0.1, sticky="n") self.entry_fc.insert(0, "50") self.entry_fc.bind('<Return>', self.plot_graph_event) self.entry_pc = tk.Entry(master, width=20, bg="lightblue") self.entry_pc.grid(row=9, column=0, padx=5, pady=0.1, sticky="n") self.entry_pc.insert(0, "0") self.entry_pc.bind('<Return>', self.plot_graph_event) self.entry_spb = tk.Entry(master, width=20, bg="lightblue") self.entry_spb.grid(row=11, column=0, padx=5, pady=0.1, sticky="n") self.entry_spb.insert(0, "50") self.entry_spb.bind('<Return>', self.plot_graph_event) def add_canvas(self, master): # Create a frame for canvas1 with a border frame1 = ttk.Frame(master, borderwidth=3, relief="groove") frame1.grid(row=0, column=1, columnspan=1, rowspan=25, padx=5, pady=5, sticky="n") # Adds canvas1 widget to frame1 self.figure1 = Figure(figsize=(13.2, 7.4), dpi=100) self.figure1.patch.set_facecolor('#F0F0F0') self.canvas1 = FigureCanvasTkAgg(self.figure1, master=frame1) self.canvas1.get_tk_widget().pack(fill=tk.BOTH, expand=True) def add_button(self, master): #Adds button self.btn1 = tk.Button(master, height=2, width=17, text="PLOT GRAPH", command=self.plot_graph) self.btn1.grid(row=12, column=0, padx=5, pady=1, sticky="n") self.btn2 = tk.Button(master, height=2, width=17, text="PLOT FFT", command=self.plot_fft_psk) self.btn2.grid(row=13, column=0, padx=5, pady=1, sticky="n") self.btn3 = tk.Button(master, height=2, width=17, text="PLOT DB", command=self.plot_fft_psk_db) self.btn3.grid(row=14, column=0, padx=5, pady=1, sticky="n") def read_and_check_input(self, fs, T, ac, fc, pc, N): try: fsampling = float(fs) except ValueError: fsampling = 1000 self.entry_fs.delete(0, tk.END) self.entry_fs.insert(0, "1000") try: periode = float(T) except ValueError: periode = 1 self.entry_periode.delete(0, tk.END) self.entry_periode.insert(0, "1") try: amp_carrier = float(ac) except ValueError: amp_carrier = 1 self.entry_ac.delete(0, tk.END) self.entry_ac.insert(0, "1") try: freq_carrier = float(fc) except ValueError: freq_carrier = 50 self.entry_fc.delete(0, tk.END) self.entry_fc.insert(0, "50") try: phi_c = float(pc) except ValueError: phi_c = 0 self.entry_pc.delete(0, tk.END) self.entry_pc.insert(0, "0") try: spb = int(N) except ValueError: spb = 50 self.entry_length.delete(0, tk.END) self.entry_length.insert(0, "50") return fsampling, periode, amp_carrier, freq_carrier, phi_c, spb def plot_graph(self): #Reads PSK params fsampling = self.entry_fs.get() periode = self.entry_periode.get() amp_carrier = self.entry_ac.get() freq_carrier = self.entry_fc.get() phase_carrier = self.entry_pc.get() spb = self.entry_spb.get() Fs, T, Ac, Fc, phi_c, samples_per_bit = self.read_and_check_input(fsampling, periode, amp_carrier, freq_carrier, phase_carrier, spb) # Performs PSK modulation t, carrier_wave, modulating_wave, ask_signal = \ self.psk_utils.calculate_psk_modulation(Fs, T, Ac, Fc, phi_c, samples_per_bit) title1 = f'Carrier Signal, frequency = {Fc}, Amplitude = {Ac}, Phase = {phi_c}' title2 = f'Modulating Signal, samples per bit = {samples_per_bit}' title3 = "PSK Modulated Signal" self.am_utils.time_domain(t, carrier_wave, title1, modulating_wave, title2, ask_signal, title3, self.figure1, self.canvas1) def plot_graph_event(self, event): self.plot_graph() def plot_fft_psk(self): #Plots FFT of signals in form1 win2 = tk.Toplevel() win2.title("PSK MODULATION (FREQUENCY-DOMAIN)") form1 = Form1(win2) #Reads PSK params fsampling = self.entry_fs.get() periode = self.entry_periode.get() amp_carrier = self.entry_ac.get() freq_carrier = self.entry_fc.get() phase_carrier = self.entry_pc.get() spb = self.entry_spb.get() Fs, T, Ac, Fc, phi_c, samples_per_bit = self.read_and_check_input(fsampling, periode, amp_carrier, freq_carrier, phase_carrier, spb) # Performs FSK modulation t, carrier_wave, modulating_wave, ask_signal = \ self.psk_utils.calculate_psk_modulation(Fs, T, Ac, Fc, phi_c, samples_per_bit) self.am_utils.plot_fft_signal(Fs, carrier_wave, \ "FFT of Carrier Signal", modulating_wave, "FFT of Modulating Signal", ask_signal, "FFT of PSK-Modulated Signal", form1.figure1, form1.canvas1) def plot_fft_psk_db(self): #Plots FFT of signals in form1 win2 = tk.Toplevel() win2.title("PSK MODULATION (FREQUENCY-DOMAIN) with DECIBLE MAGNITUDE") form1 = Form1(win2) #Reads PSK params fsampling = self.entry_fs.get() periode = self.entry_periode.get() amp_carrier = self.entry_ac.get() freq_carrier = self.entry_fc.get() phase_carrier = self.entry_pc.get() spb = self.entry_spb.get() Fs, T, Ac, Fc, phi_c, samples_per_bit = self.read_and_check_input(fsampling, periode, amp_carrier, freq_carrier, phase_carrier, spb) # Performs PSK modulation t, carrier_wave, modulating_wave, ask_signal = \ self.psk_utils.calculate_psk_modulation(Fs, T, Ac, Fc, phi_c, samples_per_bit) self.am_utils.plot_fft_db(Fs, carrier_wave, \ "Decible Magnitude of Carrier Signal", modulating_wave, "Decible Magnitude of Modulating Signal", ask_signal, "Decible Magnitude of PSK-Modulated Signal", form1.figure1, form1.canvas1) if __name__ == "__main__": window = tk.Tk() Form_PSK(window) window.mainloop()
DOWNLOAD FULL SOURCE CODE VERSION 8.0