شبیه‌سازی مقایسه‌گر تعاملی (Interactive Comparator)

برای ایجاد امکان تغییر فرکانس و به‌روزرسانی هم‌زمان گراف، باید از ابزارهای تعاملی کتابخانه matplotlib استفاده کنیم، به‌ویژه ویجت‌های اسلایدر (Slider Widgets).

این برنامه به شما این امکان را می‌دهد که با حرکت دادن دو نوار اسلایدر، فرکانس موج سینوسی و موج مثلثی را تغییر دهید و نتیجه مقایسه‌گر را بلافاصله روی نمودار مشاهده کنید.

نیازمندی‌های قبل از اجرا

اگر کد را در یک محیط پایتون اجرا می‌کنید، مطمئن شوید که محیط اجرای شما (مانند IDE یا ترمینال) از تعامل (Interactive Mode) پشتیبانی می‌کند.

کد پایتون: شبیه‌سازی مقایسه‌گر تعاملی (Interactive Comparator)

import numpy as np
import matplotlib.pyplot as plt
from scipy import signal
from matplotlib.widgets import Slider, Button # وارد کردن ویجت‌های لازم

# ----------------- کلاس OpAmp (مقایسه‌گر) -----------------
class OpAmpComparator:
    def __init__(self, v_pos=5.5, v_neg=-5.5):
        self.v_pos = v_pos
        self.v_neg = v_neg

    def transfer(self, v_plus, v_minus):
        """خروجی بر اساس مقایسه V+ و V-"""
        diff_voltage = v_plus - v_minus
        
        if diff_voltage > 0:
            return self.v_pos
        elif diff_voltage < 0:
            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)
amplitude = 4.0 # دامنه ورودی‌ها

# تعریف OpAmp
opamp = OpAmpComparator(v_pos=5.5, v_neg=-5.5)

# ----------------- تابع اصلی تولید و رسم داده‌ها -----------------

# ایجاد یک پنجره نمودار (Figure)
fig, ax = plt.subplots(figsize=(10, 7))
plt.subplots_adjust(left=0.1, bottom=0.3) # فضای لازم برای اسلایدرها

def generate_and_plot(f_sine, f_triangle):
    """
    این تابع داده‌ها را بر اساس فرکانس‌های جدید تولید کرده و آن‌ها را بازمی‌گرداند.
    """
    # 1. تولید سیگنال‌های ورودی
    V_plus_signal = amplitude * np.sin(2 * np.pi * f_sine * time)
    V_minus_signal = amplitude * signal.sawtooth(2 * np.pi * f_triangle * 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)

# ----------------- رسم اولیه و تعریف دستگیره‌های پلات (Handles) -----------------

# فرکانس‌های اولیه
f_sine_init = 1000 
f_triangle_init = 500

# تولید داده‌های اولیه
V_plus_init, V_minus_init, V_out_init = generate_and_plot(f_sine_init, f_triangle_init)

# رسم اولیه نمودار
line_plus, = ax.plot(time * 1000, V_plus_init, label='$V_+$ (Sine)', color='blue', linestyle='--')
line_minus, = ax.plot(time * 1000, V_minus_init, label='$V_-$ (Triangle)', color='green', linestyle=':')
line_out, = ax.plot(time * 1000, V_out_init, label='Output ($V_{out}$)', color='red', linewidth=2)

# تنظیمات نمودار
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='Saturation Rails')
ax.set_title('Interactive Op-Amp Comparator')
ax.set_xlabel('Time (ms)')
ax.set_ylabel('Voltage (V)')
ax.set_ylim(1.2 * opamp.v_neg, 1.2 * opamp.v_pos)
ax.grid(True)
ax.legend()


# ----------------- تعریف ویجت‌های اسلایدر -----------------

# محورها برای اسلایدر فرکانس سینوسی
ax_freq_sine = plt.axes([0.1, 0.15, 0.8, 0.03], facecolor='lightgoldenrodyellow')
slider_sine = Slider(
    ax=ax_freq_sine,
    label='Sine Freq (Hz)',
    valmin=10,
    valmax=2000,
    valinit=f_sine_init,
    valstep=10
)

# محورها برای اسلایدر فرکانس مثلثی
ax_freq_triangle = plt.axes([0.1, 0.1, 0.8, 0.03], facecolor='lightgoldenrodyellow')
slider_triangle = Slider(
    ax=ax_freq_triangle,
    label='Triangle Freq (Hz)',
    valmin=10,
    valmax=1000,
    valinit=f_triangle_init,
    valstep=10
)

# ----------------- تابع به‌روزرسانی (Update Function) -----------------

def update(val):
    """
    این تابع با تغییر اسلایدرها فراخوانی می‌شود و نمودار را به‌روز می‌کند.
    """
    # گرفتن مقادیر جدید از اسلایدرها
    f_sine_new = slider_sine.val
    f_triangle_new = slider_triangle.val
    
    # تولید داده‌های جدید
    V_plus_new, V_minus_new, V_out_new = generate_and_plot(f_sine_new, f_triangle_new)
    
    # به‌روزرسانی داده‌های خطوط (بدون نیاز به رسم مجدد کل نمودار)
    line_plus.set_ydata(V_plus_new)
    line_minus.set_ydata(V_minus_new)
    line_out.set_ydata(V_out_new)
    
    # به‌روزرسانی عناوین برای نمایش فرکانس‌های جدید
    line_plus.set_label(f'$V_+$ (Sine: {f_sine_new} Hz)')
    line_minus.set_label(f'$V_-$ (Triangle: {f_triangle_new} Hz)')
    ax.legend()
    
    fig.canvas.draw_idle() # بازسازی نمودار در زمان بیکاری

# ----------------- اتصال اسلایدر به تابع به‌روزرسانی -----------------
slider_sine.on_changed(update)
slider_triangle.on_changed(update)

# ----------------- نمایش نمودار -----------------
plt.show()

نحوه استفاده

  1. کد را اجرا کنید. یک پنجره جدید با نمودار و دو اسلایدر در پایین آن ظاهر می‌شود.
  2. اسلایدرها را جابجا کنید. با تغییر نوار Sine Freq یا Triangle Freq، مشاهده خواهید کرد که شکل موج‌های ورودی تغییر کرده و بلافاصله شکل موج مربعی خروجی (که نتیجه مقایسه آن‌هاست) به‌روزرسانی می‌شود.
  3. مشاهده رفتار مقایسه‌گر: تغییر فرکانس‌ها به شما کمک می‌کند تا ببینید چگونه لحظات تقاطع دو موج ورودی، لحظات سوئیچینگ (Switching) خروجی را تعیین می‌کنند.

همچنین بررسی کنید

ساخت پروب اسیلوسکوپ برای اندازه گیری توان (قسمت دوم)

در قسمت یک، ما محدودیت های پهنای باند پروب های غیرفعال را پوشش دادیم و …

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *