【ラズパイ】はじめてのSPI設定(ADコンバーターMAX1118)

【ラズパイ】はじめてのSPI設定(ADコンバーターMAX1118)

この記事では、ラズパイでSPI通信できるようにするまでの設定を紹介する。今回SPI通信でやりとりするのは、ADコンバーターのMAX1118となる。

MAX1118の拡大写真
MAX1118の拡大写真

MAX1118は、2チャネル、シリアル8ビットのADコンバーターだ。ADコンバーターを使えばラズパイからアナログ電圧を自由に読み取れる。SPIの設定はぜんぜん難しくないのでぜひ挑戦してみよう。

ラズパイは、Raspberry Pi zeroを使用するが、他のラズパイでも本記事と同様の方法でSPIの設定はできるはずなのでぜひ参考に。

ラズパイとADコンバーターMAX1118の配線

ADコンバーターMAX1118

MAX1118ピン端子の役割
MAX1118ピン端子の役割

ラズパイとMAX1118の配線は次の表のように接続した。

MAX1118 名称 役割 Pi接続先
1 Vdd 正電源電圧 +5V
2 Ch0 アナログ電圧入力 --
3 Ch1 アナログ電圧入力 --
4 GND グランド GND
5 (REF)I.C リファレンス入力 3.3V
6 CNVST 変換/スタート入力 SPIO CS0 (GPIO 8)
7 DOUT シリアルデータ出力 SPIO MISO (GPIO 9)
8 SCLK シリアルクロック SPIO SCLK (GPIO 11)

ラズパイではSPIで使われるCS・MOSI・MISO、SCLK、それぞれGPIO8・GPIO10・GPIO9・GPIO11に割り当てられているので注意しよう。

ラズパイGPIO役割図
ラズパイGPIO役割図

リファレンス電圧とは?

ADコンバータで必ずでてくるリファレンス電圧(Vref)とは、ADコンバータにとっての基準電圧である。たとえば、8ビットの分解能を持っているMAX1118では、このリファレンス電圧を基準に256等分してアナログ電圧を読み取ることになる。つまりリファレンス電圧を3.3Vとしたので、3.3/256で計算すると、約0.013Vの精度で電圧が読み取れる訳だ。リファレンス入力がない場合は、リファレンス電圧が内部で決められているので、データシートをよく読んで確認しておこう。

ラズパイでSPIを使えるようにするための設定

それではラズパイでSPIを使えるように設定していこう。$ sudo raspi-config を実行してSPIの設定をしていく。

下の画面で5番のInterfacing Optionsを選択。

ラズパイでSPIを設定
ラズパイでSPIを設定

P4のSPIを選択。

ラズパイでSPIを設定
ラズパイでSPIを設定

「Would you like the SPI interface to be enabled?」をYESにする。

ラズパイでSPIを設定
ラズパイでSPIを設定

以上でSPI通信が使えるようになった。

次に、PythonからSPI通信ができるようにライブラリをインストールしておこう。Python 2.x系なら $ sudo pip install spidev で、Python 3.x系なら $ sudo pip3 install spidev でインストールする。そして、$ sudo rebootでラズパイを再起動しておこう。

MAX1118のデータ送受信のフォーマット

Pythonプログラムを書く前に、ADコンバーターMAX1118の仕様を確認しておこう。MAX1118のデータシートを確認すると、CNVST に送る信号を変えることよって CH0CH1 のどちらからデータを読むかを選択できるようになっている。また、Dout からはアナログ電圧(8bit)のデータを読み取ることが可能だ。

CHO のフロー:

MAX1118のデータやりとり図
MAX1118のデータやりとり図

CH1 のフロー:

MAX1118のデータやりとり図
MAX1118のデータやりとり図

MAX1118データシートより

難しい話はさておき、実際にPythonでアナログ電圧を読み取ってみよう。手を動かしていくうちに、SPI通信のイメージがつかめるはずだ。

Pythonでアナログ電圧を読み取ってみる

それではPythonでアナログ電圧を読み取ってみる。話を簡単にするため、乾電池一本と抵抗で分圧した回路を用意した。

抵抗で分圧した回路図
抵抗で分圧した回路図

抵抗で分圧された地点をADコンバーターのCH0CH1 に接続して、それぞれの電圧をラズパイで読み取ってみよう。(GNDはRaspberry Piと共通にする。)

こんな感じで電圧値を読み取るPythonのプログラムを書いてみた。

# -*- coding: utf-8 -*-

import spidev
import time
import RPi.GPIO as GPIO


# MAX1118データシート
# http://akizukidenshi.com/download/ds/maxim/max111x.pdf


Vref = 3.335  # ラズパイの3.3V電源をテスターで実測

GPIO.setmode(GPIO.BCM)
GPIO.setup(8, GPIO.OUT)  # CNVST

spi = spidev.SpiDev()
spi.open(0, 0)  # bus0,cs0
spi.no_cs = True  # CSを使わない
spi.max_speed_hz = 1000000  # 1MHz
spi.bits_per_word = 8


def sendCNVST(CH):
    if CH == 0:
        GPIO.output(8, GPIO.LOW)
        GPIO.output(8, GPIO.HIGH)
        GPIO.output(8, GPIO.LOW)
    elif CH == 1:
        GPIO.output(8, GPIO.LOW)
        GPIO.output(8, GPIO.HIGH)
        GPIO.output(8, GPIO.LOW)
        GPIO.output(8, GPIO.HIGH)
        GPIO.output(8, GPIO.LOW)


def getVolts():
    adc = spi.xfer2([0x00])
    return adc[0] / 255.0 * Vref


try:
    while True:
        sendCNVST(0)
        v0 = getVolts()

        time.sleep(0.1)

        sendCNVST(1)
        v1 = getVolts()

        print("CH0: {:.3f}V".format(v0))
        print("CH1: {:.3f}V".format(v1))

        time.sleep(1.0)

except KeyboardInterrupt:
    spi.close()
    GPIO.cleanup()

spi.xfer2の詳しい解説はこちらを参考に。

MAX1118ではCS端子を直接操作したいので、上のプログラムでは spi.no_cs = True のようにCSを使わない設定をしている。こうしないと GPIO.output(8, GPIO.LOW) のように出来なくなるので注意が必要だ。

実際にプログラムを実行した結果がこちら。テスターで測った電圧と1/100以上の精度で一致していた。

MAX1118で電圧値を表示
MAX1118で電圧値を表示

MAX1118を使って音に反応するセンサを作ってみたので参考に。

8ch、10bitADコンバーターMCP3008(SPI通信)の記事も参考に。

記事に関するご質問などがあれば、お問い合わせ までご連絡ください。
関連記事