【ラズパイ】はじめてのSPI設定(ADコンバーターMAX1118)
この記事では、ラズパイでSPI通信できるようにするまでの設定を紹介する。今回SPI通信でやりとりするのは、ADコンバーターのMAX1118となる。
MAX1118は、2チャネル、シリアル8ビットのADコンバーターだ。ADコンバーターを使えばラズパイからアナログ電圧を自由に読み取れる。SPIの設定はぜんぜん難しくないのでぜひ挑戦してみよう。
ラズパイは、Raspberry Pi zeroを使用するが、他のラズパイでも本記事と同様の方法でSPIの設定はできるはずなのでぜひ参考に。
ラズパイとADコンバーターMAX1118の配線
ADコンバーター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に割り当てられているので注意しよう。
リファレンス電圧とは?
ADコンバータで必ずでてくるリファレンス電圧(Vref)とは、ADコンバータにとっての基準電圧である。たとえば、8ビットの分解能を持っているMAX1118では、このリファレンス電圧を基準に256等分してアナログ電圧を読み取ることになる。つまりリファレンス電圧を3.3Vとしたので、3.3/256で計算すると、約0.013Vの精度で電圧が読み取れる訳だ。リファレンス入力がない場合は、リファレンス電圧が内部で決められているので、データシートをよく読んで確認しておこう。
ラズパイでSPIを使えるようにするための設定
それではラズパイでSPIを使えるように設定していこう。$ sudo raspi-config を実行してSPIの設定をしていく。
下の画面で5番のInterfacing Optionsを選択。
P4のSPIを選択。
「Would you like the SPI interface to be enabled?」をYESにする。
以上で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 に送る信号を変えることよって CH0 と CH1 のどちらからデータを読むかを選択できるようになっている。また、Dout からはアナログ電圧(8bit)のデータを読み取ることが可能だ。
CHO のフロー:
CH1 のフロー:
MAX1118データシートより
難しい話はさておき、実際にPythonでアナログ電圧を読み取ってみよう。手を動かしていくうちに、SPI通信のイメージがつかめるはずだ。
Pythonでアナログ電圧を読み取ってみる
それではPythonでアナログ電圧を読み取ってみる。話を簡単にするため、乾電池一本と抵抗で分圧した回路を用意した。
抵抗で分圧された地点をADコンバーターのCH0 と CH1 に接続して、それぞれの電圧をラズパイで読み取ってみよう。(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を使って音に反応するセンサを作ってみたので参考に。
8ch、10bitADコンバーターMCP3008(SPI通信)の記事も参考に。