【Raspberry Pi】A/Dコンバータ MCP3208を使ってアナログ計測

A/Dコンバータ MCP3208

Raspberry Piを用いたデバイス制御には、温度センサーや距離センサーなどで周辺環境を検知することが必須です。でも、Raspberry PiにはA/Dコンバータが備わっていないんです…。

本記事では、Raspberry PiとA/DコンバータMCP3208を接続して、センサ値を読み取る方法について解説します。

目次

Raspberry Piでアナログ計測するにはA/Dコンバータが必要

Raspberry PiはArduinoとは異なり、A/Dコンバータが搭載されていません。そのため、Raspberry Piでアナログ計測するには、A/Dコンバータを別途用意しなくてはなりません。

本記事では、Microchip Technology社のMCP3208というA/Dコンバータを使用します。

MCP3208のインターフェイスはSPIという規格が採用されていますので、Raspberry PiとMCP3208はSPI接続します。

A/Dコンバータ MCP3208の仕様

MCP3208は12bitのA/Dコンバータです。

12bit = 4096刻みでアナログ値を検出出来るということです。

また、MCP3208は8つのアナログ入力信号を読み取ることが出来ます。姉妹品としてMCP3204がありますが、こちらはアナログ入力信号が4つまでに限られること以外、仕様は同じです。

Raspberry PiとA/DコンバータをSPI通信する

SPIはSerial Peripheral Interfaceの略でマイコンと周辺IC間を接続するバスです。

Raspberry PiとMCP3208にはSPIが備わっています。

両者SPIを接続し通信することで、MCP3208で読み取った値をRaspberry Piが認識することが出来ます。

SPI通信するためのspidevモジュールの使い方

MCP3208が計測したアナログ値をRaspberry Piへ送信してもらうのに、決まった通信やりとりがあります。

データシートを見ながら、自分でプログラムすることも可能ですが、結構大変です。

spidevというAPIがあるので、今回はspidevを使います。

SpiDevインスタンス生成

spi = spidev.SpiDev()

クラス内の関数を実行するためにSpiDevインスタンスを生成します。

MCP3208との接続

spi.open(port,cs)

spi.open()でMCP3208との通信を開始します。

第1引数のportは、2系統あるSPIの内どちらを使用するか選択します。SPI0なら0、SPI1なら1の数値を設定します。

第2引数のcsは、どのデバイスと通信するかです。MCP3208がCE0と接続されているなら0、CEなら1を設定します。

通信周期の設定

spi.max_speed_hz = 1000000 # 1MHz

spi.max_speed_hzに通信周波数を代入すると、その周波数で通信します。通信周波数の逆数が通信周期となります。

データ転送

xfer2(list of values)

関数xfer2で引数の値をMCP3208へ転送します。

MCP3208がアナログ計測した値をRaspberry Piに転送してもらうには、Raspberry Piからどんなデータを転送すればよいの?

MCP3208のデータシートによると、1回の通信で8bit(1byte)×3のデータ転送が必要です。Raspberry Piから下記のように転送します。

1byte目

000001
(start bit)
SGL/
DIFF
D2

2byte目

D1D0XXXXXX

3byte目

XXXXXXXX

説明にあたり、チャンネル0でアナログ計測することとします。

「SGL/DIFF」は、1(SGL): 絶対値計測か、0(DIFF): チャンネル間の差分値計測かの選択です。絶対値で計測したいので1を設定します。

絶対値計測を設定すると、3bitデータ 「D2/D1/D0」はチャンネルNo.の指定です。 チャンネルNo.指定方法は、チャンネルNo. = 4×D2 + 2×D1 + D0 となります。アナログ計測するチャンネルNo.は0ですので、D2=0、D1=0、D0=0を設定します。

「X」の値は問われませんので、0を設定します。

以上まとめると、Raspberry PiからMCP3208への転送データは、2進数表記で0b00000110、0b00000000、0b00000000、16進数表記で0x06、0x00、0x00となります。

Raspberry Piでアナログ計測してみる

準備したもの

  • Raspberry Pi Zero WH
  • ADコンバータ MCP3208
  • 赤外線距離センサ
  • 抵抗 33kΩ×1、680Ω×1
  • ブレッドボード
  • ジャンパワイヤ オス-メス

回路図

サンプルプログラム

import spidev
from time import sleep
Vref = 3.3
 
spi = spidev.SpiDev()
spi.open(0,0) #port 0,cs 0
spi.max_speed_hz = 1000000 # 1MHz

while True:
    adc = spi.xfer2([0x06,0x00,0x00])
    data = ((adc[1] & 0x0f) << 8) | adc[2]
    print (str(Vref*data/4096) + "V")
    sleep(1)
 
spi.close()

spi.xfer2()の戻り値は、MCP3208から受信したアナログ値含む8bit(1byte)×3のデータです。

データシートによるとMCP3208からの受信データは以下の定義となります。

1byte目

????????

2byte目

???0
(Null)
B11B10B9B8

3byte目

B7B6B5B4B3B2B1B0

アナログ値は2byte目の下位4bitと3byte目ですので

data = ((adc[1] & 0x0f) << 8) | adc[2]

2byte目の下位4bitのみ抽出して8bit左にシフトし、3byte目とOR条件を取ることでアナログ値となります。

赤外線センサに物体を近づけたり遠ざけたりして、アナログ値が変化するか確認

サンプルプログラムを実行し、赤外線センサに物体を近づけたり遠ざけたりしてみました。

物体を近づけたときは、0.18Vを示していたのに対し、物体を遠ざけると2.82Vを示しました。

Raspberry PiとMCP3208はSPI通信を正常に行い、Raspberry Piはセンサ値を読み取れていることが分かります。

まとめ

Raspberry PiとA/DコンバータMCP3208を接続して、センサ値を読み取る方法について解説しました。

Raspberry PiはArduinoと異なり、A/Dコンバータが搭載されていないので、A/Dコンバータを別途用意することが必要です。

今回学んだことは

  • A/Dコンバータ MCP3208の仕様について
  • SPI通信するためのspidevモジュールの使い方
  • 赤外線センサを用いたアナログ値の計測

です。

PWM制御でDCモーターの回転速度を制御する方法を学んだので、今後は周囲の環境をA/Dコンバータで検知し、DCモーターを制御する方法を解説していきたいと思います。

最後までお読み頂きありがとうございました。

プログラミング言語の人気オンラインコース
よかったらシェアしてね!
  • URLをコピーしました!

この記事を書いた人

大学で機械工学を学んだ後、製造業で働く40代の会社員です。
IT系、電気系を学んでこなかった機械系人間が、ゲーム制作、電子工作に奮闘してます。
極力低コストでものづくりを楽しむのがモットー。

目次