شبیه ساز تعاملی مقایسهگر طوریکه هر دو ورودی $V_+$ و $V_-$ از نوع موج مثلثی (Triangle Wave) باشند و فرکانس هر دو با اسلایدر و همچنین دامنه موج قابل تنظیم باشد.
این شبیهسازی، رفتار یک مقایسهگر را هنگام دریافت دو سیگنال مثلثی با فرکانسهای متفاوت نشان میدهد که میتواند در مدارهای تولید پالس پیچیده کاربرد داشته باشد.
کد پایتون: مقایسهگر دو موج مثلثی تعاملی با امکان تغییر دامنه
import numpy as np
import matplotlib.pyplot as plt
from scipy import signal
from matplotlib.widgets import Slider, Button
# ----------------- کلاس OpAmp (مقایسهگر) -----------------
# ولتاژهای اشباع ثابت میمانند
V_SUPPLY_POS = 5.5
V_SUPPLY_NEG = -5.5
class OpAmpComparator:
def __init__(self, v_pos=V_SUPPLY_POS, v_neg=V_SUPPLY_NEG):
self.v_pos = v_pos
self.v_neg = v_neg
def transfer(self, v_plus, v_minus):
"""خروجی بر اساس مقایسه V+ و V-"""
if v_plus > v_minus:
return self.v_pos
elif v_plus < v_minus:
return self.v_neg
else:
return 0
# ----------------- تنظیمات اولیه شبیهسازی -----------------
duration = 0.01 # 10 میلیثانیه
sampling_rate = 10000
time = np.linspace(0, duration, int(duration * sampling_rate), endpoint=False) # آرایه زمان (X data)
# تعریف OpAmp
opamp = OpAmpComparator()
# ----------------- تنظیمات نمودار و Handlers (مقداردهی اولیه) -----------------
# ایجاد یک پنجره نمودار (Figure)
fig, ax = plt.subplots(figsize=(10, 7))
# فضای لازم برای اسلایدرها
plt.subplots_adjust(left=0.1, bottom=0.35)
# تعریف دستگیرههای پلات (Handles) به صورت None
# این متغیرها به عنوان متغیرهای سراسری (global) در نظر گرفته میشوند.
line_plus = None
line_minus = None
line_out = None
# خطوط اشباع
ax.axhline(y=opamp.v_pos, color='gray', linestyle='-.', alpha=0.7)
ax.axhline(y=opamp.v_neg, color='gray', linestyle='-.', alpha=0.7, label='Supply Rails ($\pm 5.5V$)')
# ----------------- تابع اصلی تولید و رسم دادهها -----------------
def generate_and_plot(f_tri1, f_tri2, amplitude):
"""
تولید دو موج مثلثی با فرکانس و دامنه متغیر و شبیهسازی خروجی.
"""
# 1. تولید سیگنالهای ورودی
# V+ (ورودی غیرمعکوسکننده): موج مثلثی 1
V_plus_signal = amplitude * signal.sawtooth(2 * np.pi * f_tri1 * time, width=0.5)
# V- (ورودی معکوسکننده): موج مثلثی 2
V_minus_signal = amplitude * signal.sawtooth(2 * np.pi * f_tri2 * time, width=0.5)
# 2. شبیهسازی خروجی
V_out_signal = []
for v_plus, v_minus in zip(V_plus_signal, V_minus_signal):
v_out = opamp.transfer(v_plus, v_minus)
V_out_signal.append(v_out)
return V_plus_signal, V_minus_signal, np.array(V_out_signal)
# ----------------- تعریف ویجتهای اسلایدر -----------------
# فرکانسهای اولیه
f_tri1_init = 500
f_tri2_init = 500
amp_init = 4.0 # دامنه اولیه
# محورها برای اسلایدر فرکانس مثلثی 1 (V+)
ax_freq_tri1 = plt.axes([0.1, 0.25, 0.8, 0.03], facecolor='lightgoldenrodyellow')
slider_tri1 = Slider(ax_freq_tri1, 'Tri 1 Freq (Hz)', 50, 2000, valinit=f_tri1_init, valstep=25)
# محورها برای اسلایدر فرکانس مثلثی 2 (V-)
ax_freq_tri2 = plt.axes([0.1, 0.2, 0.8, 0.03], facecolor='lightgoldenrodyellow')
slider_tri2 = Slider(ax_freq_tri2, 'Tri 2 Freq (Hz)', 50, 1000, valinit=f_tri2_init, valstep=25)
# محورها برای اسلایدر دامنه (Amplitude)
ax_amp = plt.axes([0.1, 0.15, 0.8, 0.03], facecolor='lightcyan')
slider_amp = Slider(
ax_amp,
'Amplitude (V)',
valmin=1.0,
valmax=6.0,
valinit=amp_init,
valstep=0.1
)
# ----------------- تابع بهروزرسانی (Update Function) - بخش اصلی اصلاح شده -----------------
def update(val):
"""
این تابع مقادیر جدید را از اسلایدرها گرفته و نمودار را بهروز میکند.
"""
# تعریف متغیرهای global برای دسترسی به Handlers خطوط
global line_plus, line_minus, line_out
f_tri1_new = slider_tri1.val
f_tri2_new = slider_tri2.val
amp_new = slider_amp.val
# تولید دادههای جدید
V_plus_new, V_minus_new, V_out_new = generate_and_plot(f_tri1_new, f_tri2_new, amp_new)
# **منطق اصلاح شده:** بررسی میکند که آیا خطوط قبلاً ایجاد شدهاند یا خیر
if line_plus is None:
# اگر اولین بار است (مقداردهی اولیه)، خطوط را ایجاد کنید
line_plus, = ax.plot(time, V_plus_new, label='$V_+$ (Tri 1)', color='blue', linestyle='--')
line_minus, = ax.plot(time, V_minus_new, label='$V_-$ (Tri 2)', color='green', linestyle=':')
line_out, = ax.plot(time, V_out_new, label='Output ($V_{out}$)', color='red', linewidth=2)
else:
# در غیر این صورت، فقط دادههای Y را بهروزرسانی کنید
line_plus.set_ydata(V_plus_new)
line_minus.set_ydata(V_minus_new)
line_out.set_ydata(V_out_new)
# بهروزرسانی عناوین (Labels) در Legend
line_plus.set_label(f'$V_+$ (Tri 1: {f_tri1_new:.0f} Hz, {amp_new:.1f} V)')
line_minus.set_label(f'$V_-$ (Tri 2: {f_tri2_new:.0f} Hz, {amp_new:.1f} V)')
ax.legend()
# تنظیم محور Y
max_y = max(amp_new * 1.05, V_SUPPLY_POS * 1.05)
min_y = min(-amp_new * 1.05, V_SUPPLY_NEG * 1.05)
ax.set_ylim(min_y, max_y)
# دستور رسم مجدد
fig.canvas.draw_idle()
# ----------------- اتصال اسلایدر به تابع بهروزرسانی و نمایش اولیه -----------------
slider_tri1.on_changed(update)
slider_tri2.on_changed(update)
slider_amp.on_changed(update)
# اجرای بهروزرسانی اولیه برای نمایش نمودار با مقادیر اولیه و رفع خطای اولیه
update(None)
# ----------------- تنظیمات نهایی نمودار و نمایش -----------------
ax.set_title('Interactive Op-Amp Comparator: Freq & Amplitude Control')
ax.set_xlabel('Time (s)') # اصلاح واحد زمان
ax.set_ylabel('Voltage (V)')
ax.set_xlim(0, duration) # تنظیم محور X
plt.show()
سایت آموزشی الکترونیک و کامپیوتر اوپن مقاله های آموزشی الکترونیک و کامپیوتر و فن آوری