ラズパイでステップ応答で抵抗値の測定

抵抗とラズパイ
抵抗とラズパイ

この記事では、Raspberry Pi(ラズパイ)でステップ応答による抵抗値を測定する方法を解説していく。

ラズパイはArduinoのようなアナログ入力ピンが備えられていないため、抵抗値を測りたい場合に通常ADコンバータが必要。しかし、ADコンバータを使わなくても抵抗値を測定する方法がある。それがステップ応答による測定である。

この記事では最初にステップ応答の原理を詳わしく説明し、後半ではステップ応答による抵抗値を測定するプログラムの紹介をする。

ステップ応答による抵抗値の測定

ステップ応答による抵抗値の測定を説明していく。

まず、ステップ応答による抵抗値の測定ではコンデンサを使う。電荷が空の状態のコンデンサへ3.3Vの電圧をかける。そしてコンデンサが約1.65Vの電位(デジタルピンがHIGH)になるまでに掛かった時間を測ることで抵抗値の計算できる。

次からは回路図を使って説明していく。

抵抗値を測定する回路図

ステップ応答を使って抵抗値を測定する回路図
ステップ応答を使って抵抗値を測定する回路図

今回使用する回路は図のとおり。可変抵抗R_POTの抵抗値を測定する。

R1とR2は、ラズパイのGPIOへ過大な電流が流れ込まないようにするための保護抵抗である。話をわかりやすくするため、ここではいったん省略して説明する。また、R_POTも固定抵抗Rとして説明する。すると、次のようなシンプルな回路図になる。

抵抗値を測定する回路図簡略版
抵抗値を測定する回路図簡略版

ステップ応答で測定する手順

これから簡略した回路図を使って、ステップ応答で測定する手順を説明していく。

手順は次の通り。

  1. コンデンサを放電する
  2. コンデンサの電荷を空にする
  3. コンデンサへ充電するを開始する
  4. コンデンサの電位を1.65V以上にする

❶コンデンサを放電する

コンデンサの放電中
コンデンサの放電中

はじめに、コンデンサの電荷をすべて放電しておく。そのため図のようにA点のGPIOを入力モードにし、B点のGPIOを出力モードに設定する。また、B点はLOWに設定しGNDと同じ電位にする。

A点は入力モードのためハイインピーダンスとなり、ほとんど電流は流れない。だから、コンデンサに溜まった電荷はB点を通して放電される。

❷コンデンサの電荷を空にする

コンデンサが空になった状態
コンデンサが空になった状態

コンデンサの電荷が空の状態、つまりコンデンサの電圧が0Vの状態にしておく。これで充電を開始する準備が整った。

❸コンデンサへ充電を開始する

コンデンサへ充電中
コンデンサへ充電中

コンデンサへ充電を開始すると同時に、この瞬間から時間の測定を行う。

コンデンサへ充電をするためには、A点のGPIOを出力モードにしHIGHの状態に設定する。また、B点のGPIOは入力モードに設定する。

A点はHIGHのため3.3Vの信号を出力する。B点はハイインピーダンスなので電流がほとんど流れない。よって、A点から電流が抵抗Rを通してコンデンサCへ充電されていく。Rの抵抗値が大きいほど充電に時間がかかり、抵抗値が小さいほど充電時間は短くなる。

❹コンデンサの電位を1.65V以上にする

コンデンサの電位が約1.65Vを超えた時
コンデンサの電位が約1.65Vを超えた時

コンデンサへ電荷が溜まっていくと、B点の電圧は上がっていく。そして約1.65Vを超えた瞬間、B点のデジタル入力はHIGHとなる。この時までに掛かった時間、つまりコンデンサの電圧が0Vから約1.65Vまで上がるのに掛かった時間をt秒とする。

RC直列回路における抵抗値Rを算出する計算式

RC直列回路における抵抗値Rを算出する計算式の説明をする。

ここでは、抵抗R[Ω]・コンデンサC[F]・直流電源E[V]とした。

コンデンサの電圧を時間関数Vc(t)[V]として経過時間t[s]を図で表すと次のようになる。

コンデンサの電位が約1.65Vを超えた時
コンデンサの電位が約1.65Vを超えた時

この時、コンデンサの電圧Vc(t)は次式で表される。つまり図の青い曲線のことである。

$$ v_c(t) = E(1 - e^{-\frac{1}{CR}{t}}) \tag1$$

この式をtで微分すると、青い曲線の傾きがわかる。微分した結果は次の通り。

$$ \frac{dVc(t)}{dt} = Et + \frac{E}{CR}e^{-\frac{1}{CR}t} \tag2$$

この式にt=0を代入すると次の式が導き出される。これが図の赤い直線の傾きである。

$$ V=\frac{E}{CR}t \tag3 $$

さて、0Vから1.65Vまではほぼ時間と比例してコンデンサの電圧は上昇していく。つまり赤い線と青い線は1.65Vまでは同じ傾きだとみなせる。だから式3を展開してRを求める事ができる。

$$ R = \frac{E}{CV}t \tag4$$

ここでは、E=3.3[V]、C=0.1x10^-6[F]、V=1.65[V]である。これらを式4へ代入すると抵抗値Rは次式で求められる。

$$\bf R = \frac{3.3}{0.1\times1.65} \times t \times10^{6} \tag5 $$

可変抵抗の値を計算する

ステップ応答を使って抵抗値を測定する回路図
ステップ応答を使って抵抗値を測定する回路図

話を最初に戻して、もう一度可変抵抗と保護抵抗を含めた回路図を確認しよう。図の回路が今回ラズパイで使用する回路だ。

R1とR_POTの2つの抵抗を介してコンデンサへ充電されるわけだからRの値は次のようになる。

$$ R = R1 + R_{POT} \tag6$$

これを式5へ代入すると次式が導き出された。

$$ \bf R_{POT} = \frac{3.3}{0.1\times1.65} \times t \times10^{6} - R1 \tag7$$

よって、R_POTの抵抗値はコンデンサが0Vから1.65Vへ変化するまでの経過時間tを測ることで計算が可能となる。

ラズパイと可変抵抗の配線

ラズパイと可変抵抗の配線図
ラズパイと可変抵抗の配線図

それでは実際に図のようにラズパイと可変抵抗・抵抗・コンデンサを配線してみよう。

ステップ応答で抵抗値を測定するプログラム

最後にステップ応答で抵抗値を測定するプログラムを紹介する。このプログラムは「Raspberry Piクックブック」の本を元に改良したものだ。プログラム中、間違ってる箇所があったのでそこも修正した。ここまでの説明とプログラミング中のコメントアウトを追えば、何をやっているかは理解できる思う。

# -*- coding: utf-8 -*-
import time
import RPi.GPIO as GPIO

C = 0.1  # 0.1uF
R1 = 1000  # 保護抵抗のR1=1kΩ
E = 3.3  # 電圧
V = 1.65

GPIO.setmode(GPIO.BCM)

a_pin = 18  # GPIO18
b_pin = 23  # GPIO23


# コンデンサの放電
def discharge():
    GPIO.setup(a_pin, GPIO.IN)  # ハイインピーダンスのためAへ電流は流れない
    GPIO.setup(b_pin, GPIO.OUT)
    GPIO.output(b_pin, False)  # 点BがLOWになるのでコンデンサが放電される
    time.sleep(0.1)  # 放電が完了するまで少し待つ


# コンデンサの電位が約1.65V以上になるとデジタルピンはHIGHになる
def charge_time():
    GPIO.setup(b_pin, GPIO.IN)  # 入力モード
    GPIO.setup(a_pin, GPIO.OUT)  # 出力モード
    GPIO.output(a_pin, True)  # Aから抵抗を介してコンデンサへ電流が流れ、蓄電される
    t1 = time.time()
    while not GPIO.input(b_pin):  # HIGHになるまで監視
        pass
    t2 = time.time()
    return (t2 - t1) * 1000000  # コンデンサがμFの単位なので、時間をμ秒に直している


def analog_read():
    discharge()  # 放電
    t = charge_time()  # 充電
    # print("{}μS".format(t))
    discharge()  # 放電
    return t


# 充電時間から抵抗値を計算する
def read_resistance():
    n = 10
    total = 0
    for i in range(1, n):  # 10回充放電を繰り返し、その平均値を充電に掛かった時間とする
        total = total + analog_read()
    t = total / float(n)
    r = ((E * t) / (C * V)) - R1  # R=T/C(ただしR1は保護抵抗なので差し引く)
    # T = 0.632 * t * E  # オリジナル
    # r = (T / C) - R1  # オリジナル
    return r


try:
    while True:
        print("{:.1f}Ω".format(read_resistance()))
        time.sleep(0.5)
finally:
    GPIO.cleanup()

プログラムの実行結果

プログラムを実行して可変抵抗のつまみを回せば0Ωから10kΩまでの変化を確認できるはず。しかし、可変抵抗だといまいち精度がわかりずらいので100kΩの固定抵抗に付け替えて測定してみた。その結果がこちら。

$ python step_pot.py 
104540.3Ω
104974.2Ω
105378.6Ω
105611.7Ω
146706.0Ω
106033.3Ω
106059.5Ω
106346.1Ω
106479.1Ω
167304.0Ω
106658.4Ω
106626.4Ω

ご覧の通りステップ応答で測定したときの精度はそれほど良くない。そもそもコンデンサの値は10%ほどの誤差が含まれている。また、ときどき明らかにおかしいな値を計測してしまう事があるため、プログラムをもう少し改善する必要があるかもしれない。しかし、ステップ応答による測定はADコンバータを使わなくて済むので、用途によっては非常に便利な方法である。

記事に関するご質問などがあればTwitterへお返事ください。
この記事で紹介した商品
人気のラズパイ
人気のラズパイ周辺機器
Raspberry Piのオススメ入門書
関連記事