【Raspberry Pi】ADコンバータMCP3008の使い方【SPI通信】

はじめに
この記事では、Raspberry Pi(以下ラズパイ)とADコンバータMCP3008を使ってアナログ電圧を読み取る方法をご紹介いたします。 MCP3008は、8chで10bitの分解能を持つADコンバータです。 Raspberry PiとMCP3008のやりとりはSPI通信で行います。
MCP3008のピン役割
MCP3008のピン役割を説明します。
MCP3008のピンは次の図のように割り振られてます。
それぞれのピンの役割は次の表のとおりです。
MCP3008 | 名称 | 役割 |
---|---|---|
1 | CH0 | アナログ電圧入力 |
2 | CH1 | アナログ電圧入力 |
3 | CH2 | アナログ電圧入力 |
4 | CH3 | アナログ電圧入力 |
5 | CH4 | アナログ電圧入力 |
6 | CH5 | アナログ電圧入力 |
7 | CH6 | アナログ電圧入力 |
8 | CH7 | アナログ電圧入力 |
9 | DGND | デジタルGND |
10 | CS/SHDN | チップセレクト/シャットダウン |
11 | Din | シリアルデータIN |
12 | Dout | シリアルデータOUT |
13 | CLK | シリアルクロック |
14 | AGND | アナログGND |
15 | Vref | リファレンス電圧 |
16 | Vdd | 電源電圧 (+2.7〜5.5V) |
チャネルをどうやって切り替えるのか?
MCP3008では8チャネルのアナログ電圧を読み取ることができます。コンフィギュレーションビットの信号を変えることで、各チャネルを指定できます。
Single/Diff | D2 | D1 | D0 | CH |
---|---|---|---|---|
1 | 0 | 0 | 0 | CH0 |
1 | 0 | 0 | 1 | CH1 |
1 | 0 | 1 | 0 | CH2 |
1 | 0 | 1 | 1 | CH3 |
1 | 1 | 0 | 0 | CH4 |
1 | 1 | 0 | 1 | CH5 |
1 | 1 | 1 | 0 | CH6 |
1 | 1 | 1 | 1 | CH7 |

Single/Diff
ビットは1に固定しましたが、0に設定すると
differential
モードとなり、チャネル間での差分信号を読み取ることが可能です。
詳しくはMCP3008データシートご覧ください。 http://akizukidenshi.com/download/ds/microchip/mcp3008.pdf
Raspberry PiとMCP3008の配線
Raspberry PiとMCP3008を次のように配線します。
MCP3008 | 名称 | ラズパイ物理番号 | ラズパイ名称 |
---|---|---|---|
9 | DGND | 6 | GND |
10 | CS/SHDN | 24 | CS0 (GPIO 8) |
11 | Din | 19 | MOSI (GPIO 10) |
12 | Dout | 21 | MISO (GPIO 9) |
13 | CLK | 23 | SCLK (GPIO 11) |
15 | Vref | 17 | 3.3V |
16 | Vdd | 1 | 3.3V |
ブレッドボードとジャンプワイヤを使って次のように接続しました。
SPIの設定
Raspberry PiでSPIを使うには、初期設定が必要です。
また、Raspberry PiのSPIで使われるCS・MOSI・MISO、SCLKは、それぞれGPIO8・GPIO10・GPIO9・GPIO11にあらかじめ割り当てられてます。ご注意ください。

MOSIとMISO
MOSI
と MISO
はマスターから信号を送るか、スレーブから信号を受け取るかの違いです。MOSIはマスターアウトスレーブイン、MISOはマスターインスレーブアウトの略です。今回の場合、マスターはRaspberry
Piであり、スレーブはADコンバータのMCP3008になります。
Raspberry PiとMCP3008でアナログ電圧を読み取るプログラム
それでは実際に、Raspberry PiとMCP3008でアナログ電圧を読み取ってみましょう。温度センサTMP36の電圧を読み取ってみます。 次は、そのプログラム例です:
import time
import spidev
= 3.334 # 電圧をテスターで実測する
Vref
= spidev.SpiDev()
spi
open(0, 0) # bus0,cs0
spi.= 100000 # 100kHz 必ず指定する
spi.max_speed_hz
def readAdc(channel):
= spi.xfer2([1, (8 + channel) << 4, 200])
adc = ((adc[1] & 3) << 8) + adc[2]
data return data
def convertVolts(data, vref):
= (data * vref) / float(1023)
volts return volts
def convertTemp(volts):
= (volts - 0.75) / 0.01 + 25.0
temp return temp
if __name__ == '__main__':
try:
while True:
= readAdc(channel=0)
data = convertVolts(data, Vref)
volts = convertTemp(volts)
temp print("CH0 volts: {:.2f}".format(volts))
print("temp : {:.2f}".format(temp))
# data = readAdc(channel=1)
# volts = convertVolts(data, Vref)
# print("CH1 volts: {:.2f}".format(volts))
2)
time.sleep(
except KeyboardInterrupt:
spi.close()
注意点としまして、サンプリングレートを明示してあげないと、うまく動作せず正しいデータが取り出せませんでした。また、MCP3008のサンプリングレートはVddが5Vのとき最大で200ksps、2.7Vの時では75kspsまでです。今回Vddは3.3Vなので、サンプリングレートを100kspsに設定しました。
関連記事
- 【Raspberry Pi】ADコンバータMCP3425の使い方
- Raspberry PiでSPI通信できるようにする設定【ADコンバータMAX1118】
- Arduinoで可変電圧器【Seeeduino Xiao】
- ADコンバータADS1115の使い方【ESP32・Arduino】
- M5StickC PLUSの内蔵ADコンバータで電圧測定