2019年5月23日木曜日

MPC3208 ADconverter


https://qiita.com/shiraco/items/8c2587ae5a647b4f9803#%E4%B8%BB%E5%BD%B9   から

彼らがAD変換の主役です。本記事で解説します。
  • 12ビットADコンバータ MCP3208-CI/P x 1
    • アナログ値をデジタル値に変換します
  • 半固定抵抗 x 1
    • 抵抗値を変化させアナログ値をセンシングします
  • フォトレジスタ x 1
    • 抵抗値を変化させアナログ値をセンシングします

脇役

ちなみに彼らも必要ですが、本記事では解説しません。
  • RaspberryPi一式
  • 抵抗(330Ω) x 1
  • 赤色LED x 1
  • ブレッドボード x 1
  • ジャンパワイヤ
    • オス-メス x 1セット
    • オス-オス x 1セット

AD変換とは?

アナログ値をデジタル値に変換します。

なぜデジタル値が必要なのか?

RaspberryPiへの入力は基本的には、2進数として、LOW(0)/HIGH(1) 2つの状態のどちらかになる。
これは、部屋の明るさだと、明かりがついているか消えているか、の2段階として理解します。

これをデジタル値、0-4095のような段階的な値として入力することを狙います。

そもそもアナログ値、デジタル値って?

  • アナログ値
    • 連続値
    • e.g. 明るさ、温度、電圧など
  • デジタル値
    • 飛び飛びの値(離散値)
    • e.g. 計測して桁を切り捨てた値(デジタル時計)など

AD変換 (画像引用元: Raspberry Piで学ぶ電子工作|ブルーバックス)

adc.jpg
  • 1. センサからのアナログ値の取得
  • 2. AD変換
  • 3. デジタル値の通信

1. センサからのアナログ値の取得:

特定の地点での抵抗値を変化させ、端子から出力させるアナログ電圧を変化させる(0V-3.3V)1.65V
  • 半固定抵抗
  • フォトレジスタ (CdSセル)

半固定抵抗?

P-06110.jpg
画像引用元: akizukidenshi.com
  • 可変抵抗の一つで抵抗の大きさを調整可能

フォトレジスタ (CdSセル)?

I-00110.jpg
画像引用元: akizukidenshi.com

2. AD変換

アナログ電圧を測定しその値を、ADコンバータにてAD変換しデジタル値にする(0-4095->12bit) 2048
  • ADコンバータ

ADコンバータ?

(12ビットADコンバータ MCP3208-CI/P)
I-00238.JPG
画像引用元: akizukidenshi.com

ADコンバータ特徴

  • 16ピンを持つ回路
    • 0ch-7chの8つのアナログ値を読み取れるチャネル
  • アナログ値をデジタル値に変換する
  • 12ビット精度で送れる
    • 212=4096=4103
スクリーンショット 2016-11-22 1.59.36.png

3. シリアル通信

デジタル値を2進数 (1000_0000_0000 = 2048) としてSPI通信で送る
  • SPI通信
  • I2C通信

3. シリアル通信

スクリーンショット 2016-11-22 1.55.37.png

code

# MCP3208からSPI通信で12ビットのデジタル値を取得。0から7の8チャンネル使用可
def readadc(adcnum, clockpin, mosipin, misopin, cspin):
    if adcnum > 7 or adcnum < 0:
        return -1
    GPIO.output(cspin, GPIO.HIGH)
    GPIO.output(clockpin, GPIO.LOW)
    GPIO.output(cspin, GPIO.LOW)

    commandout = adcnum
    commandout |= 0x18  # スタートビット+シングルエンドビット
    commandout <<= 3    # LSBから8ビット目を送信するようにする
    for i in range(5):
        # LSBから数えて8ビット目から4ビット目までを送信
        if commandout & 0x80:
            GPIO.output(mosipin, GPIO.HIGH)
        else:
            GPIO.output(mosipin, GPIO.LOW)
        commandout <<= 1
        GPIO.output(clockpin, GPIO.HIGH)
        GPIO.output(clockpin, GPIO.LOW)
    adcout = 0
    # 13ビット読む(ヌルビット+12ビットデータ)
    for i in range(13):
        GPIO.output(clockpin, GPIO.HIGH)
        GPIO.output(clockpin, GPIO.LOW)
        adcout <<= 1
        if i>0 and GPIO.input(misopin)==GPIO.HIGH:
            adcout |= 0x1
    GPIO.output(cspin, GPIO.HIGH)
    return adcout
inputVal0 = readadc(0, SPICLK, SPIMOSI, SPIMISO, SPICS)

演習1

スクリーンショット 2016-11-21 0.22.03.png
06-01-print.py
    while True:
        inputVal0 = readadc(0, SPICLK, SPIMOSI, SPIMISO, SPICS)
        print(inputVal0)

演習2

スクリーンショット 2016-11-21 0.22.10.png
06-02-led.py
    while True:
        inputVal0 = readadc(0, SPICLK, SPIMOSI, SPIMISO, SPICS)
        if inputVal0 < 2000:
            GPIO.output(LED, GPIO.HIGH)
        else:
            GPIO.output(LED, GPIO.LOW)

演習3

06-03-volume.py
    while True:
        inputVal0 = readadc(0, SPICLK, SPIMOSI, SPIMISO, SPICS)
        vol = "{0}%".format(int(inputVal0*100/4095))
        if vol != vol_old:
            print(vol)
            args = ['amixer','-q','cset','numid=1',vol]
            subprocess.Popen(args)
            vol_old = vol

まとめ

  • AD変換することで、センサーに入力されたアナログ値をデジタル値として回路から利用することができる
  • AD変換はADコンバーターを使って行う
  • デジタル値の通信はSPI通信でおこなう
なお、AD変換の仕組みはRaspberry Piで学ぶ電子工作(ブルーバックス)にわかりやすくまとまっているので、みなさん買って読みましょう。

参考

書籍

回路




0 件のコメント:

コメントを投稿