サイトロゴ

Raspberry PiでSPI通信できるようにする設定【ADコンバータMAX1118】

著者画像
Toshihiko Arai

はじめに

この記事では、Raspberry PiでSPI通信できるようにするまでの設定を紹介します。今回SPI通信でやりとりするデバイスとして、ADコンバータのMAX1118を使いました。また、Raspberry Pi zeroを使用しましたが、他のRaspberry Piでも構いません。SPIの設定は簡単ですのでぜひ挑戦なさってみてください。

Raspberry PiとADコンバータMAX1118の配線

ADコンバータMAX1118の仕様

MAX1118ピン端子の役割は下図の通りです。

配線

次の表の通りRaspberry Piと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)

Raspberry Piでは、SPIで使われるCS・MOSI・MISO、SCLKがあらかじめGPIO8・GPIO10・GPIO9・GPIO11ピンに割り当てられているので注意しましょう。

リファレンス電圧とは?

ADコンバータでよく出てくるリファレンス電圧(Vref)について触れておきます。リファレンス電圧とはADコンバータにとっての基準電圧のことです。たとえば、8ビットの分解能を持っているMAX1118では、このリファレンス電圧を基準に256等分してアナログ電圧を読み取る仕様になってます。リファレンス電圧が3.3Vだとしたら、3.3÷256で約0.013Vの精度で電圧が読み取れる理屈になります。外部端子にリファレンス入力がない場合は、ADコンバータ内部で設けられているはずです。データシートで確認しておくと良いでしょう。

Raspberry PiでSPIを使えるようにするための設定

ここからはRaspberry PiでSPIを使えるようにする設定方法を紹介します。

Raspberry PiへSSHでログイン後、$ sudo raspi-config を実行します。下の画面で5番のInterfacing Optionsを選択。

次にP4のSPIを選択します。

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

以上です。たったこれだけの設定ですが、SPI通信が使えるようになりました。

PythonでSPI通信の設定

次に、PythonからもSPI通信ができるようにライブラリをインストールしておきます。Python 2.x系なら $ sudo pip install spidev で、Python 3.x系なら $ sudo pip3 install spidev でインストールします。その後 $ sudo reboot でRaspberry Piを再起動したら完了です。

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

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

CHO のフロー:

CH1 のフロー:

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

ざっくりとこんな感じで通信してるんだなぁ、と頭に留めておく程度で構いません。難しい話は抜きで、ここからは実際にPythonでアナログ電圧を読み取ってみます。手を動かしていくうちに、SPI通信のイメージがつかめるはず。

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

Pythonを使ってRaspberry Piでアナログ電圧を読み取ってみます。作業を簡単にするため、乾電池一本と抵抗で分圧した回路を用意しました。

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

次はADコンバータで電圧値を読み取るPythonのプログラムです。


import spidev
import time
import RPi.GPIO as GPIO




Vref = 3.335  # Raspberry Piの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以上の精度で一致してましたから、なかなかすごい精度です。

関連記事