t-hom’s diary

主にVBAネタを扱っているブログ…とも言えなくなってきたこの頃。

分圧回路によってアナログ1ピンで複数スイッチを判別する際の推奨抵抗値を求めるVBAプログラム

Arduino等を使った電子工作で複数スイッチを使いたいとき、スイッチの数だけピンを使ってしまうとあっという間にピンが足りなくなってしまう。

組み込むスイッチ数が多い場合は、抵抗の分圧回路を使ってアナログピンに掛かる電圧を読み取ることで、1つのアナログピンでどのスイッチが押されているのかを判別させることができる。

少々ややこしい話だけど、各スイッチが押されたときの電流経路とAnalog Inputに入る電圧の計算式は次のとおり。

前回作った分圧回路はすべて1kΩの抵抗を使ったが、これだとスイッチが増えるほど電圧差がなだらかになってしまい、ノイズ等の要素で電圧がふらついた際に誤動作する恐れがある。

そこで抵抗の値を以下のようにうまく調整することで、綺麗に電圧を分割して多少ノイズが乘ってもしっかりどのボタンが押されたか判別できるようにしたい。

理想の抵抗値を計算すると5Vの10分割となり0.5V単位で増えるのだが、実際には販売されている抵抗から近い値のものを使うことになるので上記のように小数点以下に誤差が出る。※さらに製品自体の許容誤差もあるので計算通りにはならない。
このあたりの話は、以下のサイトに詳しく掲載されている。感謝。
synapse.kyoto

ただスイッチの個数が変わる度に理想の抵抗値を手計算で求めるのはかなり面倒くさい。
ということで、VBAでプログラムを書いてみた。

コード

Option Explicit

'スイッチ数と抵抗R1の値を以下で調整する。
Const NUMBER_OF_SWITCHS As Integer = 6
Const R1 As Double = 10000

'以下を実行すると上記の条件における推奨の抵抗値を表示する。
Sub PrintRecommendedRegisters()
    Dim ideal_register_values As Collection: Set ideal_register_values = New Collection
    Dim voltage_divider_ratio As Double
    Dim i As Integer
    For i = 0 To NUMBER_OF_SWITCHS - 1
        voltage_divider_ratio = (1 / NUMBER_OF_SWITCHS) * i
        ideal_register_values.Add (voltage_divider_ratio / (1 - voltage_divider_ratio)) * R1
    Next
    
    Debug.Print "R1: " & R1 & "Ω"
    Dim j As Integer
    For j = 2 To ideal_register_values.Count
        Debug.Print "R" & Trim(Str(j)) & ": " & ConvertToE24(ideal_register_values.Item(j) - ideal_register_values.Item(j - 1)) & "Ω"
    Next
    
End Sub

'計算で求めた抵抗値を与えると、実際に購入可能な抵抗値(E24系)から近いものを選択して返す関数
Function ConvertToE24(arg)
    Dim e24 As Variant
    e24 = Array(1, 1.1, 1.2, 1.3, 1.5, 1.6, 1.8, 2, 2.2, 2.4, 2.7, 3, 3.3, 3.6, 3.9, 4.3, 4.7, 5.1, 5.6, 6.2, 6.8, 7.5, 8.2, 9.1)
    Dim c As Collection: Set c = New Collection
    
    Dim exp As Integer
    exp = 0
    Do Until 9.1 * 10 ^ exp > arg
        exp = exp + 1
    Loop
    
    Dim minimum_difference As Double
    minimum_difference = 9.1 * 10 ^ exp
    
    Dim closest_value As Double
    closest_value = 9.1 * 10 ^ exp
    
    Dim j As Integer
    Dim i As Integer
    For j = exp - 1 To exp
        For i = LBound(e24) To UBound(e24)
            Dim difference As Double
            difference = Abs(e24(i) * 10 ^ j - arg)
            If difference < minimum_difference Then
                minimum_difference = difference
                closest_value = e24(i) * 10 ^ j
            End If
        Next
    Next
    
    ConvertToE24 = closest_value
End Function

実行結果

NUMBER_OF_SWITCHSの値とR1の抵抗値を任意の値に変えて実行するとイミディエイトウインドウに推奨抵抗値が表示される。

理想の抵抗値を計算した後、実際に販売されているE24系の抵抗値に数値を丸めて表示している。

リストにまとめてみた

逐一プログラムを動かすのも面倒なので表にしてみた。
これでボタンを使ったプロジェクトで逐一計算する必要がなくなった。

以上

当ブログは、amazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイト宣伝プログラムである、 Amazonアソシエイト・プログラムの参加者です。