はじめに
趣味のアナログ回路開発で、手持ち部品ストックの抵抗器を組み合わせて、目的とする抵抗値を作り出したいというシチュエーションが時々発生します。
そんな時に便利な算出アプリを Gemini の支援を受けながら作成しました。
前提条件
私の環境では、抵抗レンジによりますが「E24系列は全部揃えてないけど、E12系列はだいたい網羅」という感じで揃えています。個人レベルだと似たような感じの方が多いのではないでしょうか。
そこで今回は、「E24系列の中からリストアップしてもらい、その中から良さそうな組み合わせを選び出す」という、半自動的なアプローチでの簡易的なアプリ作成を目的とします。
最終的には、誤差ランクを選別したリストもデータベースとして持たせた、自前の在庫管理システムと紐付けて完全自動抽出アプリなんていうのも面白そうですが。
参考までに、我が家でストックしている抵抗(金皮抵抗)はこんなイメージ。
| ~9.2Ω | 10Ω~ | 100Ω~ | 1kΩ~ | 10kΩ~ | 100kΩ~ | 1MΩ~ | E12 | E24 |
|---|---|---|---|---|---|---|---|---|
| 1.0 | 10 | 100 | 1k | 10k | 100k | 1M | o | o |
| 1.1 | 11 | 110 | 1.1k | 11k | 110k | o | x | |
| 1.2 | 12 | 120 | 1.2k | 12k | 120k | o | o | |
| 1.3 | 13 | 130 | 1.3k | 13k | 130k | o | x | |
| 1.5 | 15 | 150 | 1.5k | 15k | 150k | o | o | |
| 1.6 | 16 | 160 | 1.6k | 16k | 160 | o | x | |
| 1.8 | 18 | 180 | 1.8k | 18k | 180k | o | o | |
| 2.0 | 20 | 200 | 2k | 20k | 200k | 2M | o | x |
| 2.2 | 22 | 220 | 2.2k | 20k | 220k | o | o | |
| 2.4 | 24 | 240 | 2.4k | 24k | 240k | o | x | |
| 2.7 | 27 | 270 | 2.7k | 27k | 270k | o | o | |
| 3.0 | 30 | 300 | 3k | 30k | 300k | 3M | o | x |
| 3.3 | 33 | 330 | 3.3k | 33k | 330k | o | o | |
| 3.6 | 36 | 360 | 3.6k | 36k | 360k | o | x | |
| 3.9 | 39 | 390 | 3.9k | 39k | 390k | o | o | |
| 4.3 | 43 | 430 | 4.3k | 43k | 430k | o | x | |
| 4.7 | 47 | 470 | 4.7k | 47k | 470k | o | o | |
| 5.1 | 51 | 510 | 5.1k | 51k | 510k | o | x | |
| 5.6 | 56 | 560 | 5.6k | 56k | 560k | o | o | |
| 6.2 | 62 | 620 | 6.2k | 62k | 620k | o | x | |
| 6.8 | 68 | 680 | 6.8k | 68k | 680k | o | o | |
| 7.5 | 75 | 750 | 7.5k | 75k | 750k | o | x | |
| 8.2 | 82 | 820 | 8.2k | 82k | 820k | o | o | |
| 9.1 | 91 | 910 | 9.1k | 91k | 910k | o | x |
太字 は保有、 斜体 は非保有を意味します。
ソフト仕様
- 開発言語はPython、StreamlitによるGUIアプリとする
- 目的抵抗値と許容誤差をUIで入力する
- 近似値算出はE24系列の抵抗1~3本の組み合わせパターンとする
- 3本ペアを含むか含まないかをUIで選択
- 下記検索パターンとする
1本単体・2本直列・2本並列・3本直列・3本並列・3本直並列。 - 検索範囲は1Ω~3MΩとする。
- 総当たり法でソートし誤差(目標値に対する相対誤差率)の少ないものからリストアップする
- 組み合わせコストの大小(1本<2本<3本)は考慮しない
そこまでの自動化はせず、提示したリストの中からユーザーに判断させる方針。
作成コード
import streamlit as st
import pandas as pd
# E12/E24系列の基本値(1.0 ~ 9.1)
E12_BASE = [
1.0, 1.2, 1.5, 1.8, 2.2, 2.7, 3.3, 3.9, 4.7, 5.6, 6.8, 8.2
]
E24_BASE = E12_BASE + [
1.1, 1.3, 1.6, 2.0, 2.4, 3.0, 3.6, 4.3, 5.1, 6.2, 7.5, 9.1
]
@st.cache_data
def get_e24_resistors(min_val=1.0, max_val=10_000_000.0):
"""指定範囲内のE24系列の抵抗値リストを生成する"""
resistors = []
multiplier = 1.0
while multiplier <= max_val:
for b in E24_BASE:
val = b * multiplier
if min_val <= val <= max_val:
resistors.append(val)
multiplier *= 10
return sorted(resistors)
def calc_parallel(r1, r2):
"""並列抵抗の合成値を計算"""
if r1 + r2 == 0:
return 0
return (r1 * r2) / (r1 + r2)
def main():
st.set_page_config(page_title="E24 抵抗コンビネーション電卓", layout="wide")
st.title("🔌 E24系列 抵抗組み合わせオプティマイザー")
st.write("目的の抵抗値に最も近い1〜3本の抵抗の組み合わせを算出。")
# --- サイドバー設定 ---
st.sidebar.header("検索条件")
target = st.sidebar.number_input("目標抵抗値 (Ω)", min_value=0.1, max_value=10_000_000.0, value=1000.0, step=1.0)
max_count = st.sidebar.selectbox("最大使用本数", [2, 3], index=0)
tolerance = st.sidebar.slider("許容誤差 (±%)", min_value=0.01, max_value=5.0, value=1.0, step=0.01) / 100.0
num_results = st.sidebar.slider("表示件数", min_value=5, max_value=50, value=15)
# 抵抗の探索範囲(1Ω 〜 3MΩ)
resistors = get_e24_resistors(1.0, 3_000_000.0)
if st.button("計算実行", type="primary"):
with st.spinner("最適な組み合わせを計算中..."):
results = []
# 1. 1本の場合
for r1 in resistors:
err = (r1 - target) / target
if abs(err) <= tolerance:
results.append({
"合成抵抗 (Ω)": r1,
"誤差 (%)": err * 100,
"構成": "1本",
"詳細": f"{r1:g} Ω"
})
if max_count >= 2:
# 2本直列
for i in range(len(resistors)):
for j in range(i, len(resistors)):
r1, r2 = resistors[i], resistors[j]
r_val = r1 + r2
err = (r_val - target) / target
if abs(err) <= tolerance:
results.append({
"合成抵抗 (Ω)": r_val,
"誤差 (%)": err * 100,
"構成": "2本直列",
"詳細": f"{r1:g} + {r2:g}"
})
# 2本並列
for i in range(len(resistors)):
for j in range(i, len(resistors)):
r1, r2 = resistors[i], resistors[j]
r_val = calc_parallel(r1, r2)
err = (r_val - target) / target
if abs(err) <= tolerance:
results.append({
"合成抵抗 (Ω)": r_val,
"誤差 (%)": err * 100,
"構成": "2本並列",
"詳細": f"{r1:g} // {r2:g}"
})
if max_count >= 3:
# 3本直列: R1 + R2 + R3
for i in range(len(resistors)):
for j in range(i, len(resistors)):
for k in range(j, len(resistors)):
r1, r2, r3 = resistors[i], resistors[j], resistors[k]
r_val = r1 + r2 + r3
err = (r_val - target) / target
if abs(err) <= tolerance:
results.append({
"合成抵抗 (Ω)": r_val,
"誤差 (%)": err * 100,
"構成": "3本直列",
"詳細": f"{r1:g} + {r2:g} + {r3:g}"
})
# 3本並列: R1 // R2 // R3
for i in range(len(resistors)):
for j in range(i, len(resistors)):
for k in range(j, len(resistors)):
r1, r2, r3 = resistors[i], resistors[j], resistors[k]
denom = (1/r1) + (1/r2) + (1/r3)
r_val = 1 / denom if denom > 0 else 0
err = (r_val - target) / target
if abs(err) <= tolerance:
results.append({
"合成抵抗 (Ω)": r_val,
"誤差 (%)": err * 100,
"構成": "3本並列",
"詳細": f"{r1:g} // {r2:g} // {r3:g}"
})
# 直並列1: R1 + (R2 // R3)
for i in range(len(resistors)):
for j in range(len(resistors)):
for k in range(j, len(resistors)):
r1 = resistors[i]
r2, r3 = resistors[j], resistors[k]
r_val = r1 + calc_parallel(r2, r3)
err = (r_val - target) / target
if abs(err) <= tolerance:
results.append({
"合成抵抗 (Ω)": r_val,
"誤差 (%)": err * 100,
"構成": "直並列 (R + R//R)",
"詳細": f"{r1:g} + ({r2:g} // {r3:g})"
})
# 直並列2: (R1 // R2) + R3
for i in range(len(resistors)):
for j in range(i, len(resistors)):
for k in range(len(resistors)):
r1, r2 = resistors[i], resistors[j]
r3 = resistors[k]
r_val = calc_parallel(r1, r2) + r3
err = (r_val - target) / target
if abs(err) <= tolerance:
results.append({
"合成抵抗 (Ω)": r_val,
"誤差 (%)": err * 100,
"構成": "直並列 ((R//R) + R)",
"詳細": f"({r1:g} // {r2:g}) + {r3:g}"
})
if not results:
st.warning("指定した許容誤差の範囲内に一致する組み合わせが見つかりませんでした。許容誤差を広げるか、条件を確認してください。")
else:
# 誤差の絶対値が小さい順にソート
results.sort(key=lambda x: abs(x["誤差 (%)"]))
# 重複する合成抵抗値を適度にまとめる(またはそのまま上位表示)
df = pd.DataFrame(results[:num_results])
st.success(f"条件に一致する候補が {len(results)} 件見つかりました(上位 {min(num_results, len(results))} 件を表示)")
# データフレームの表示
st.dataframe(
df.style.format({
"合成抵抗 (Ω)": "{:.4f}",
"誤差 (%)": "{:+.3f}%"
}),
use_container_width=True
)
if __name__ == "__main__":
main()
E24系列のリストでイテレータを回しソートするだけという、至極単純なコードです。
実行
Streamlit のインストール(インストールしていない場合)。
pip install streamlit
スクリプト実行。
streamlit run guiter_sim_web.py
Webブラウザが立ち上がる。こんな感じのUI。
このサンプルでは、992Ω ± 0.5% を目標抵抗値として設定した結果を表示している。
990Ω + 82Ω を直列接続した組み合わせがドンピシャで、(上に掲示した表から)このどちらも保有ストックにあるので、先ずはこれから試してみよう……という作業フローになります。
もし在庫を切らしてたりしていれば、次の候補の 1kΩ + 120kΩ の並列接続ペアが -0.027% と十分許容範囲に入っているので、こちらを試してみる……という使い方ができる。
なお、アプリ詳細欄の”//”は並列接続を示します。
使い勝手としては、もう少し改善の余地がある気もするが、個人レベルの便利ツールとしては十分だろう、という結論になりました。
今後の展開など
今回は汎用的なアプリ作成を通してチュートリアル的なことをやってみたが、上述の通り、保有リストでフィルタをかけたり、データベースと紐付けしたりといった、より用途に最適化したパーソナル・カスタマイズへの応用も、やろうとすればできそう。
熟練のアナログ職人なら、このようなツールを使わずとも、これまで培った勘と経験でパッと思い付くのでしょうが(なので、こういったツールはあまり聞いたことが無い)、趣味レベルの人間ではそうはいかない。
こういったツールを揃えることで、生産性改善につなげていけるかな、と次の一手を考えている所です。
