【ラズパイ電子工作】SPI通信でADコンバータの値を読み取る方法(MCP3002)

【ラズパイ電子工作】SPI通信でADコンバータの値を読み取る方法(MCP3002)

SPI(Serial Peripheral Interface)とは、ICなどの電子部品と通信するために使用される通信方法の一種です。旧モトローラ社が提唱した規格で、汎用性が高いことから広く使われています。

デバイス間を繋ぐ信号線が4本(3本の場合もある)であり、数Mbpsの通信が可能といった特徴があります。

ADコンバータとは、アナログ(A)信号を入力して、入力電圧に応じたデジタル(D)信号を出力する部品です。

この記事では、ラズベリーパイのプログラム(Python)からSPI通信を用いてADコンバータに接続された半固定ボリュームの値を読み取る方法を解説します。

注意
この記事中に記載されている内容はソースコード含めて電気設計人が自己流で行ったものです。一般的な方法とは相違がある可能性がありますので予めご了承ください。

1. 完成イメージ(ADコンバータの値を読み取る)

この記事で完成するものは以下のようになります。

10_完成イメージ

半固定ボリュームを回すと、実行結果は以下のように1~1023の数値が表示されます。

11_完成イメージ(表示)

半固定ボリュームを右に回すと数値が増大します。

2. 使用する部品

今回使用する部品は以下の通りです。

ラズベリーパイ本体(モデル3B+)

20_ラズベリーパイ3B+

『Raspberry Pi 3 Model B+』を使用します。※2020年6月時点で最新はRaspberry Pi 4になります。

ブレッドボード

20_ブレッドボート

LEDや抵抗といった各種部品や(後述する)ジャンパ線などを穴に差し込み、部品間を電気的に接続する板(ボード)です。

電子工作をする上で必須の部品です。

ジャンパ線

20_ジャンパ線

ブレッドボートに差し込み、電子部品の間を電気的に接続します。

↑の写真では両側が「ピン」になっており、ブレッドボートの穴に差し込んで使用します。

ADコンバータ:MCP3002

MCP3002

(小さくてすいません…)

今回はSPI通信に対応したADコンバータであるMCP3002を使用します。各ピンの機能は以下のようになります。

MCP3002データシート
出典:MCP3002データシート
1:CS/SHDN:チップセレクト
2:CH0:チャンネル0 アナログ入力
3:CH1:チャンネル1 アナログ入力
4:Vss:GND
5:Din:シリアルデータ入力
6:Dout:シリアルデータ出力
7:CLK:シリアルクロック
8:Vdd/Vref:電源(+2.7V~5.5V)

半固定ボリューム

ボリューム

半固定ボリューム(半固定抵抗器)は、ツマミを回すと抵抗値が変化する部品です。今回は0~10kΩ範囲の抵抗値を可変できる半固定ボリュームを使用します。

オススメの電子工作セット

電子工作をするため、これまで解説した部品の他にもスイッチやセンサなど、色々な部品が必要になってきます。個々で購入するには手間がかかるため、最初はセット品を購入することをおススメします。

電気設計人
電気設計人

私は以下のセット品を購入しました!

注意
ADコンバータ:MCP3002はこのセット内には入っていませんので、別途購入が必要です。

また、これからラズベリーパイを購入する場合、ラズベリーパイ本体を含めたセット品を購入することをおススメします。

ラズベリーパイ本体を収めるケースや、OSをインストールするためmicroSDカードなど必要なものを個々に購入する手間を省くことができます。

3. 回路図・配線の様子

ラズベリーパイのプログラム(Python)からSPI通信を用いてADコンバータに接続された半固定ボリュームの値を読み取る回路を解説します。

回路図

回路図は以下のようになります。

30_回路図

SPI通信をする場合「制御するデバイスをマスタ」「制御されるデバイスをスレーブ」と呼び、マスタとスレーブは4本の信号線で接続します。

今回のようにラズベリーパイでADコンバータの値を読み取る場合、「マスタがラズベリーパイ」「スレーブがADコンバータ」となります。

メモ
マスタ(Master)に対して、スレーブ(Slave)とは奴隷という意味です。

ラズベリーパイをADコンバータ(MCP3002)とSPI通信するため、以下のように接続します。

ラズベリーパイのピンMCP3002のピンジャンパ線
SPICS0CS/SHDN(1番ピン)白色
SPIMOSIDin(5番ピン)黄色
SPIMISODout(6番ピン)青色
SPISCLKCLK(7番ピン)白色

白色が被ってしまいました…ジャンパ線はこの色でなければいけない訳ではありません。


MCP3002と半固定ボリュームを接続する必要があります。今回はMCP3002のCH0(2番ピン)に接続します。(青色のジャンパ線)

3.3VとGNDをMCP3002と半固定ボリュームに各々接続します。(オレンジ色と黒色のジャンパ線)

配線の様子

配線の様子です。こんな感じになりました。

31_配線の様子

↑では、フラットケーブルでGPIOの全ピンをブレッドボードに接続しています。回路図と実際の配線は異なる部分がありますがご了承ください。

※電気的には「回路図」と同じ意味です。

4. プログラム(Python)

SPI通信を用いてADコンバータに接続された半固定ボリュームの値を読み取るプログラム(Python)は以下のようになります。

ソースコード

#必要なモジュールをインポート
import spidev                       #SPI通信用のモジュールをインポート
import time                         #時間制御用のモジュールをインポート
import sys                          #sysモジュールをインポート

#SPI通信を行うための準備
spi = spidev.SpiDev()               #インスタンスを生成
spi.open(0, 0)                      #CE0(24番ピン)を指定
spi.max_speed_hz = 1000000          #転送速度 1MHz

#連続して値を読み込む
while True:
    try:
        resp = spi.xfer2([0x68, 0x00])                 #SPI通信で値を読み込む
        volume = ((resp[0] << 8) + resp[1]) & 0x3FF    #読み込んだ値を10ビットの数値に変換
        print(volume)                                  #変換した値を表示
        time.sleep(1)                                  #1秒間待つ

    except KeyboardInterrupt:
        #Ctrl+Cキーが押された
        spi.close()                            #SPI通信を終了
        sys.exit()                             #プログラム終了

SPI通信でMCP3002の値を読み取り、変換して画面に表示します。

プログラムの解説

#必要なモジュールをインポート
import spidev                       #SPI通信用のモジュールをインポート
import time                         #時間制御用のモジュールをインポート
import sys                          #sysモジュールをインポート

2~4行目で今回必要な「モジュール」を宣言します。


#SPI通信を行うための準備
spi = spidev.SpiDev()               #インスタンスを生成
spi.open(0, 0)                      #CE0(24番ピン)を指定
spi.max_speed_hz = 1000000          #転送速度 1MHz

SPI通信をする準備をします。SpiDev()メソッドはspiという名称でSPI通信をできるようにします。

spi.open(0, 0)は、CE0(24番ピン)に接続したデバイスと通信を開始します。CE1(26番ピン)に接続したデバイスと通信する場合はspi.open(0, 1)と記述します。


#連続して値を読み込む
while True:
    try:
        resp = spi.xfer2([0x68, 0x00])                 #SPI通信で値を読み込む
        volume = ((resp[0] << 8) + resp[1]) & 0x3FF    #読み込んだ値を10ビットの数値に変換
        print(volume)                                  #変換した値を表示
        time.sleep(1)                                  #1秒間待つ

    except KeyboardInterrupt:
        #Ctrl+Cキーが押された
        spi.close()                            #SPI通信を終了
        sys.exit()                             #プログラム終了

「while文」は条件を指定して、その条件が真の時に繰り返し処理を行うものです。

Python
while 条件式:
    繰り返し処理を行うコード

↑の「条件式」にTrueを指定することにより、条件式は常に真となりwhile文は無限に繰り返します。

メモ
無限に繰り返すことを、無限ループと表現したりします。

ただし、このままではプログラム実行中に無限ループから抜け出す方法がありません。そこでwhile文の中にある「try文」と「except文」を使用します。

このtry-except文を用いることにより、while文の処理は以下のようになります。

Python
while True:
    try:
        繰り返し処理を行うコード
    except KeyboardInterrupt:               #Ctrl+Cキーが押された
        spi.close()                         #SPI通信を終了
        sys.exit()                          #プログラムを終了

except KeyboardInterrupt:は、キーボードのCtrl + cキーが押された時にwhile文の繰り返し処理から抜けて「GPIOのクリーンアップ」と「プログラムの終了」の処理を行います。

Ctrl + cキーが押されていないとき、try:文の中の処理を繰り返し行います。(以下で解説)


while文の中の「繰り返し処理を行うコード」は以下の通りです。つまり、Ctrl + Cキーが押されるまで以下の処理を繰り返します。

    resp = spi.xfer2([0x68, 0x00])                 #SPI通信で値を読み込む
    volume = ((resp[0] << 8) + resp[1]) & 0x3FF    #読み込んだ値を10ビットの数値に変換
    print(volume)                                  #変換した値を表示
    time.sleep(1)                                  #1秒間待つ

spi.xfer2([0x68, 0x00])では、MCP3002のCH0(チャンネル0 アナログ入力)のアナログ値を取得します。

MCP3002から取得したデータはresp[0]resp[1]の2バイトに分かれます。シフト演算子を用いて1ヶにまとめます。

time.sleep(1)は何もせずに1秒間待ちます。

5. おわりに

ラズベリーパイのプログラム(Python)からSPI通信を用いてADコンバータに接続された半固定ボリュームの値を読み取る方法を解説しました。

SPI通信を使用すると、電子工作の幅がグッと広がります。

まだまだラズベリーパイ初心者の私ですが、以下の参考書が大変参考にさせて頂いております。

2冊とも初学者にも易しい内容になっており、ゼロからラズベリーパイを始める方にもオススメできる参考書です。

1 COMMENT

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です