0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Pythonで学ぶCMOSイメージセンサー

Posted at

1. 光電変換

Q_ph = q * N_ph  
N_ph = (η * P_opt * t_int) / (hν)  
V_sig = Q_ph / C_FD  

光子数 (N_{ph}) は入射光パワー (P_{opt})、露光時間 (t_{int})、および光子エネルギー (h\nu) から決まる。
量子効率 (\eta) を考慮すると、発生電荷 (Q_{ph}) は光の強さに比例。
その電荷がフローティング拡散容量 (C_{FD}) に蓄積され、信号電圧 (V_{sig}) が生じる。
これはCMOSイメージセンサーの1ピクセル出力電圧の基本式。


2. 画素読み出しとADC要求速度

f_s = (M * N) / T_frame

1フレームあたり (M×N) 画素を (T_{frame}) 秒で読み出す必要がある。
例:100万画素を30fpsで出力 → 約30 Msps。
このためCCD時代は高速パイプラインADCが必要だった。


3. シングルスロープADCの基本構造

V_ramp(t) = (V_ref / T_ramp) * t  
V_in = S * t_conv  
S = V_ref / T_ramp  
t_conv = V_in / S = T_ramp * (V_in / V_ref)  
D = N_clk * (V_in / V_ref)
  • 入力電圧 (V_{in}) と線形ランプ電圧 (V_{ramp}(t)) を比較。
  • 比較器出力が切り替わる時刻 (t_{conv}) が電圧に比例。
  • この時間をクロックでカウントしてデジタル値 (D) を生成。

つまり「電圧 → 時間 → カウント数」に変換する積分型(計数型)A/D変換


4. 方式別ADC動作速度

f_ADC(CCD) ≥ (M * N) / T_frame  
f_ADC(CMOS) ≥ N / T_frame
  • CCDでは出力1系統 → 1個の高速ADCが全画素を逐次処理。
  • CMOSではカラムごとにADCを配置(列並列)。
    よって1列あたりの処理速度で済み、必要速度は約 (1/M) に低減。

5. まとめ

  • 光→電荷→電圧変換は (V = Q/C)。
  • CCDは単一高速パイプラインADC方式
  • CMOSは多並列シングルスロープADC方式で、低消費・高並列化。
  • 基本関係は全て時間変換式 (t_{conv} = T_{ramp}(V_{in}/V_{ref})) に基づく。

import numpy as np
import matplotlib.pyplot as plt

# ==============================
# 定数 / Constants
# ==============================
q = 1.602e-19          # 電子電荷 [C]
h = 6.626e-34          # プランク定数 [J*s]
c = 3.0e8              # 光速 [m/s]
λ = 550e-9             # 光の波長 [m]
ν = c / λ              # 光の周波数 [Hz]
η = 0.6                # 量子効率 (Quantum Efficiency)
C_FD = 10e-15          # フローティング拡散容量 [F]
P_opt = 1e-9           # 入射光パワー [W]
t_int = 10e-3          # 露光時間 [s]
V_ref = 1.0            # 参照電圧 [V]
T_ramp = 10e-6         # ランプ期間 [s]
N_clk = 1024           # クロック数

# ==============================
# 1. 光電変換 / Photoelectric Conversion
# ==============================
N_ph = (η * P_opt * t_int) / (h * ν)
Q_ph = q * N_ph
V_sig = Q_ph / C_FD

print("=== Photoelectric Conversion ===")
print(f"Photon count N_ph = {N_ph:.2e}")
print(f"Generated charge Q_ph = {Q_ph:.2e} [C]")
print(f"Signal voltage V_sig = {V_sig:.3f} [V]")

# ==============================
# 2. 画素読み出しとADC速度要求 / Frame readout speed
# ==============================
M, N = 1000, 1000       # Pixels (1M)
T_frame = 1 / 30        # 30 fps
f_s_CCD = (M * N) / T_frame
f_s_CMOS = N / T_frame

print("\n=== ADC Speed Requirement ===")
print(f"CCD ADC speed ≥ {f_s_CCD/1e6:.1f} Msps")
print(f"CMOS ADC speed ≥ {f_s_CMOS/1e3:.1f} ksps (per column)")

# ==============================
# 3. シングルスロープADC動作 / Single-Slope ADC
# ==============================
S = V_ref / T_ramp
V_in_values = np.linspace(0, V_ref, 5)
t_conv_values = T_ramp * (V_in_values / V_ref)
D_values = N_clk * (V_in_values / V_ref)

print("\n=== Single-Slope ADC ===")
for Vin, tconv, D in zip(V_in_values, t_conv_values, D_values):
    print(f"V_in={Vin:.2f} V → t_conv={tconv*1e6:.2f} μs → D={int(D)}")

# ==============================
# 4. 可視化 / Visualization
# ==============================
t = np.linspace(0, T_ramp, 200)
V_ramp = S * t
V_in_demo = 0.7 * V_ref
t_cross = T_ramp * (V_in_demo / V_ref)

plt.figure()
plt.plot(t * 1e6, V_ramp, label="Ramp Voltage V_ramp(t)")
plt.axhline(V_in_demo, color="r", linestyle="--", label="Input Voltage V_in")
plt.axvline(t_cross * 1e6, color="g", linestyle=":", label="t_conv (cross point)")
plt.xlabel("Time [μs]")
plt.ylabel("Voltage [V]")
plt.title("Single-Slope ADC Conversion (Voltage → Time)")
plt.legend()
plt.grid(True)
plt.show()
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?