LoginSignup
19
19

More than 5 years have passed since last update.

【Ruby】 抵抗器を表現するgemをつくった

Last updated at Posted at 2015-01-19

概要

抵抗器のカラーコードを抵抗値に変換したり、合成抵抗を計算したりするgemをつくりました。名前は resistor です。レジスタと聞いて最初に思い浮かぶ方のレジスタ(register)ではなく抵抗器を意味するレジスタ(resistor)です。

インストール

$ gem install resistor

追記(更新内容)

gemの更新内容を追記していきます。
それに伴い記事の内容も編集するので予めご了承ください。

2015/02/11 v1.0.0

  • Resistor.newする際にohmやcodeを指定しないよう変更
  • error_range としていた部分を全て tolerance に変更
  • 合成抵抗を計算するメソッドにそれぞれエイリアスを追加(#+に#-, #/に#|)

2015/02/15 v1.1.0

  • 5本帯に対応
  • 5本帯用にE48,E96系列判定メソッドを追加

抵抗のカラーコード

抵抗のカラーコードは4本帯の場合、例えば 「茶赤茶金」 となっていたら

12*10^1 = 120 [Ω]

になります。1、2本目は有効数字、3本目は乗数、4本目の色は許容差で、その辺にある4本帯では金(±5%)であることが多いです。

それぞれの色と数値の対応は以下のようになっています。

数値 乗数 許容差
黒 (black) 0 10^0
茶 (brown) 1 10^1 ±1%
赤 (red) 2 10^2 ±2%
橙 (orange) 3 10^3 ±0.05%
黄 (yellow) 4 10^4
緑 (green) 5 10^5 ±0.5%
青 (blue) 6 10^6 ±0.25%
紫 (purple) 7 10^7 ±0.1%
灰 (gray) 8 10^8
白 (white) 9 10^9
銀 (silver) 10^-2 ±10%
金 (gold) 10^-1 ±5%

ひとつ目の機能としてこのカラーコード変換の計算をやってくれます。

require 'resistor'

# 抵抗値 -> カラーコード
Resistor::ColorCode.encode(4700)
# => [:yellow, :purple, :red, :gold]

# カラーコード -> 抵抗値
Resistor::ColorCode.decode([:yellow, :purple, :red, :gold])
# => 4700.0

Resistor::ColorCode.encode

  • 抵抗値[Ω]を渡すとカラーコードの配列(要素がシンボルの配列)が返ってくる
  • Resistor::ColorCode.encode(100, tolerance: 1) のようにすると許容差を指定できる
  • 0を渡すと [:black] が返ってくる
  • 0.1Ω以上99MΩ以下までの数値で正しい結果が返ってくる

Resistor::ColorCode.decode

  • カラーコードの配列(要素がシンボルか文字列の配列)を渡すと抵抗値[Ω]が返ってくる
  • [:black] を渡すと0.0が返ってくる
  • 配列以外のものを渡されるとつらい
  • 先ほどの表以外の色が要素に含まれているとつらい

いい名前が思い浮かばなかったので抵抗値をカラーコードに変換することをエンコード、その逆をデコードとしました。

0Ωの抵抗だけは黒黒黒とかでなく黒一本なのでここでもそれに従いました。

合成抵抗の計算

require 'resistor'

Resistor.new(20)
# => #<Resistor::BasicResistor:0x00000000f205a8 @ohm=20.0, @code=[:red, :black, :black, :gold], @tolerance=5.0>
Resistor.new(['red', 'red', 'red', 'gold'])
# => #<Resistor::BasicResistor:0x00000000f03f48 @ohm=2200.0, @code=[:red, :red, :red, :gold], @tolerance=5.0>

上記のように抵抗値(Integer, Float)かカラーコード(Array)のどちらかを渡すことで、抵抗値( @ohm )、カラーコード( @code )、許容差( @tolerance )をインスタンス変数にもったオブジェクトをつくることができます。

このクラスのオブジェクトには合成抵抗を計算するメソッドがあり、 直列接続 のときは +並列接続 のときは / を使います。

require 'resistor'

r1 = Resistor.new(20)
r2 = Resistor.new(30)
r3 = Resistor.new(4)
r4 = Resistor.new(8)

直列の場合

# --[r1]--[r2]--[r3]--

r5 = r1 + r2 + r3
p r5.ohm
# => 54.0

並列の場合

#     --[r2]--
# -- |--[r2]--|--
#     --[r2]--

r5 = r2 / r2 / r2
p r5.ohm
# => 10.0

直列と並列の組合せ

#    --[r1]--          --[r4]--
# --|        |--[r3]--|        |--
#    --[r2]--          --[r4]--

r5 = (r1 / r2) + r3 + (r4 / r4)
p r5.ohm
# => 20.0

余談ですが合成抵抗を計算するメソッドの戻り値は Resistor.new してできたオブジェクトとは異なり @ohm しかインスタンス変数がありません。

合成抵抗を計算して出てきた値が必ずしもきれいな値になるとは限らず、その値をそのまま保持しておきたかったからです。合成抵抗を計算するメソッドはどちらのクラスのオブジェクトにもあるので、上記のように計算ができます。

5本帯抵抗

v1.1.0から5本帯抵抗に対応しました。4本帯がデフォルトになっていますが、いくつかの方法で5本帯に切り替えることができます。

オプションで指定するとその場限りで5本帯用の処理をしますが、毎回オプションで指定しなくてもいいように、デフォルト値自体を変更するメソッドもあります。

  • Resistor.new(2.21, band_number: 5) のようにオプションで指定します。
  • Resistor::ColorCode.encode(100, band_number: 5) decodeも同様に指定できます。
  • Resistor::Options.set_band_number 以降のデフォルト値を変更できます。引数は4か5のみで、それ以外の数字を渡しても しかし なにも おこらなかった!

set_band_number を使うとオプションで指定する際と異なり、許容差のデフォルト値も同時に変更されます。また、4本帯では許容差5%、5本帯では許容差1%をセットにしていますが、強引にオリジナルのデフォルト値のセットを指定することもできます。

require 'resistor'

# 以降全てのデフォルトが5本帯で許容差1%に変更される
Resistor::Options.set_band_number 5

Resistor.new(2.21)
# => #<Resistor::BasicResistor:0x00000002933b48 @ohm=2.21, @code=[:red, :red, :brown, :silver, :brown], @tolerance=1.0>
Resistor::ColorCode.encode(100)
# => [:brown, :black, :black, :black, :brown]


# 以降全てのデフォルトが5本帯で許容差0.5%に変更される
Resistor::Options.defaults do |d|
  d[:band_number] = 5
  d[:tolerance] = 0.5
end

Resistor.new(2.21)
# => #<Resistor::BasicResistor:0x00000001717ae0 @ohm=2.21, @code=[:red, :red, :brown, :silver, :green], @tolerance=0.5>
Resistor::ColorCode.encode(100)
# => [:brown, :black, :black, :black, :green]

E系列の判定

抵抗器やコンデンサの値は、E系列という規格化された数列表に基づいた値になっていて、許容差5%の抵抗の場合はE24系列というものが使われています。

そこで Resistor.new でつくられたオブジェクトに対してどの系列であるかを調べるメソッドをつくりました。

本来、E系列は許容差と関係があるのですが、ここでは単純にカラーコードの数字だけをみて真偽を判定します。

このgemではE系列の内、

  • #e12? E12系列であるなら true ,それ以外は false
  • #e24? E24系列であるなら true ,それ以外は false
  • #e48? E48系列であるなら true ,それ以外は false (5本帯専用)
  • #e96? E96系列であるなら true ,それ以外は false (5本帯専用)

の4つが使えます。 #e48? , #e96? に関しては4本帯の抵抗である場合、常に偽となります。

require 'resistor'

r1 = Resistor.new(4700)
r2 = Resistor.new(62)

r1.e12? # => true
r1.e24? # => true
r2.e12? # => false
r2.e24? # => true

Resistor::Options.set_band_number 5

r3 = Resistor.new(105)
r4 = Resistor.new(4.99)

r3.e48? # => true
r3.e96? # => true
r4.e48? # => false
r4.e96? # => true

おわりに

今回初めてgemを自作してみたのですが、とてもいい勉強になりました。

ソースコードは ここ にあったりなかったりします。

ご意見、ご感想、ごマサカリ等お待ちしております。

19
19
6

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
19
19