شبیه سازی OpAmp با ولتاژ آفست ورودی (Input Offset Voltage)

ما مدل Op-Amp شما را به یک شبیه‌سازی کامل و کاربردی تبدیل خواهیم کرد.

تا اینجا ما رفتار Op-Amp را در سه حوزه مهم مدل‌سازی کردیم:

  1. اشباع (Saturation): محدودیت‌های ولتاژ تغذیه.
  2. نرخ چرخش (Slew Rate): محدودیت سرعت تغییر.
  3. پهنای باند (Bandwidth): محدودیت فرکانسی.

اما یک Op-Amp واقعی محدودیت حیاتی دیگری نیز دارد: ولتاژ آفست ورودی (Input Offset Voltage).

افزودن ولتاژ آفست ورودی ($V_{os}$)

یک Op-Amp ایده‌آل زمانی که $V_{in+} = V_{in-}$ باشد، خروجی صفر می‌دهد. اما در واقعیت، به دلیل عدم تقارن در ساختار داخلی (ترانزیستورها)، باید اختلاف ولتاژ کوچکی (در حد میلی‌ولت) بین ورودی‌ها اعمال شود تا خروجی دقیقاً صفر شود.

این ولتاژ کوچک ($\pm V_{os}$) به ورودی اضافه می‌شود و در حلقه بسته توسط بهره مدار تقویت می‌شود، که منجر به یک خطا (DC Error) در خروجی می‌شود.

کد پایتون: اضافه کردن آفست ورودی و جمع‌بندی

کد زیر، تمام مدل‌های قبلی را در یک کلاس نهایی ادغام می‌کند و $V_{os}$ را نیز اضافه می‌کند.

Python

import numpy as np
import matplotlib.pyplot as plt

class CompleteOpAmp:
    def __init__(self, v_pos=15, v_neg=-15, slew_rate=0.5e6, # V/s
                 v_offset=2e-3, # Input Offset Voltage (2mV)
                 ideal_gain=10, # Closed loop gain target for simulation
                 ):
        
        # پارامترهای اصلی
        self.v_pos = v_pos
        self.v_neg = v_neg
        self.slew_rate = slew_rate
        self.v_offset = v_offset 
        self.ideal_gain = ideal_gain
        self.prev_output = 0 # برای محاسبات Slew Rate
        
        # بهره نویز DC (ولتاژ آفست نیز با این بهره تقویت می‌شود)
        # برای تقویت‌کننده معکوس: A_noise = 1 + (Rf / Rin)
        # توجه: چون بهره ما 10- است، (Rf/Rin) = 10 است
        self.dc_noise_gain = 1 + abs(ideal_gain) 
        
    def calculate_output(self, target_voltage, dt):
        
        # --- 1. افزودن ولتاژ آفست به ورودی تفاضلی ---
        # این ولتاژ باعث می‌شود خروجی حتی بدون سیگنال ورودی، مقداری ولتاژ DC داشته باشد
        # در اینجا ما اثر آن را مستقیماً به ولتاژ مورد نیاز اضافه می‌کنیم:
        
        # محاسبه ولتاژ DC خطا در خروجی (Output DC Error)
        # Error = Vos * Noise_Gain
        offset_error = self.v_offset * self.dc_noise_gain
        
        # ولتاژ مورد نظر به علاوه خطای آفست
        target_v_out = target_voltage + offset_error

        # --- 2. اعمال محدودیت Slew Rate ---
        
        delta_v = target_v_out - self.prev_output
        max_change = self.slew_rate * dt
        
        if abs(delta_v) > max_change:
            actual_change = max_change * np.sign(delta_v)
        else:
            actual_change = delta_v
            
        new_output = self.prev_output + actual_change
        
        # --- 3. اعمال محدودیت اشباع (Saturation) ---
        
        if new_output > self.v_pos:
            final_output = self.v_pos
        elif new_output < self.v_neg:
            final_output = self.v_neg
        else:
            final_output = new_output
            
        # ذخیره برای دور بعدی
        self.prev_output = final_output
        return final_output

# --- تنظیمات شبیه‌سازی نهایی ---

duration = 0.005 # 5 میلی‌ثانیه
sampling_rate = 1000000 # 1 مگاهرتز
time = np.linspace(0, duration, int(duration * sampling_rate))
dt = time[1] - time[0]

# --- نمونه‌سازی OpAmp ---
# بهره حلقه بسته 10- است (مثلا Rf=10k, Rin=1k)
# Slew Rate نسبتاً کند: 0.5 V/us = 500,000 V/s
my_opamp = CompleteOpAmp(v_pos=10, v_neg=-10, slew_rate=5e5, ideal_gain=-10)

# --- تولید سیگنال ورودی ---
# موج سینوسی با فرکانس 1kHz
freq = 1000 
amplitude = 0.5 # 0.5 ولت
# تولید سیگنال سینوسی
v_in_signal = amplitude * np.sin(2 * np.pi * freq * time)

# افزودن نویز به ورودی
noise_level = 0.01 
v_in_noisy = v_in_signal + np.random.normal(0, noise_level, len(time))

# --- حلقه شبیه‌سازی ---
v_out_signal = []

for v_in in v_in_noisy:
    # هدف مدار: Vin * Gain (منفی چون معکوس‌کننده است)
    target_v_out = v_in * my_opamp.ideal_gain 
    
    # محاسبه خروجی با تمام محدودیت‌ها (Slew Rate, Saturation, Offset)
    real_out = my_opamp.calculate_output(target_v_out, dt)
    v_out_signal.append(real_out)

# --- رسم نمودار ---

plt.figure(figsize=(10, 6))
plt.title('Complete Op-Amp Simulation (Offset, Slew Rate, Noise)')
plt.plot(time * 1e3, v_in_noisy, label='Noisy Input', color='blue', alpha=0.5)
plt.plot(time * 1e3, v_out_signal, label='Real Output', color='red', linewidth=2)

# رسم خطای DC ناشی از آفست
dc_offset_line = my_opamp.v_offset * my_opamp.dc_noise_gain
plt.axhline(y=dc_offset_line, color='purple', linestyle=':', label='Output DC Error')

# رسم محدودیت‌های تغذیه
plt.axhline(y=my_opamp.v_pos, color='green', linestyle='--', alpha=0.6)
plt.axhline(y=my_opamp.v_neg, color='green', linestyle='--', alpha=0.6, label='Supply Rails')

plt.xlabel('Time (ms)')
plt.ylabel('Voltage (V)')
plt.grid(True)
plt.legend()
plt.show()

تحلیل عملکرد نهایی Op-Amp

این مدل نهایی Op-Amp، رفتار یک تراشه واقعی را به صورت جامع‌تر منعکس می‌کند:

  1. خطای DC (آفست):
    • به خط بنفش نقطه‌چین در نمودار توجه کنید. این خط نشان‌دهنده خطای DC در خروجی است که به دلیل $V_{os}$ داخلی ایجاد شده و توسط بهره نویز (Noise Gain) تقویت شده است.
    • در این مثال، $V_{offset} = 2 mV$ و $A_{noise} = 11$. بنابراین خطای DC حدود $22 mV$ است و کل موج خروجی را به سمت بالا جابجا می‌کند.
  2. Slew Rate و پهنای باند:
    • اگر فرکانس (مثلاً 1kHz) در محدوده‌ی پهنای باند باشد، شکل سینوسی حفظ می‌شود. اما اگر فرکانس را بسیار بالا ببرید (مثلاً 50kHz) یا دامنه را افزایش دهید، Op-Amp قادر به دنبال کردن سیگنال نخواهد بود و اثر Slew Rate (موج ذوزنقه‌ای) پدیدار می‌شود.
  3. نویز:
    • اگر دامنه نویز ورودی را افزایش دهید، لرزش موج خروجی (خط قرمز) نیز افزایش می‌یابد.
  4. اشباع (Clipping):
    • اگر دامنه ورودی را (مثلاً) به $1.5V$ افزایش دهید، خروجی مورد انتظار ($\pm 15V$) از ولتاژ تغذیه ($\pm 10V$) فراتر می‌رود و قله‌های موج بریده خواهند شد.

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

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

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

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

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