稼働中

Raspberry Pi Pico(d_07)MCP3008 A/D変換

MCP3008 A/D (SPI)

Microchip社のMCP3008は分解能10bitの8チャンネルのA/Dコンバータです。SPI通信で制御します。
Raspberry Pi PicoでMCP3008を使ってみました。
※micro:bitの記事(e_31)からRaspberry Pi Picoで使えるように追記、修正しました。

外観

MCP3008の外観写真とピン配置です。※ピン配置はMicrochipのデータシートより抜粋
MC3008外観ピン配置

接続図

MCP3008の動作電圧が2.7~5.5VなのでRaspberry Pi Picoの3.3Vから供給できます。
SPI通信はGP0(SPI0 RX)、GP1(SPI0 CSn)、GP2(SPI0 SCK)、GP3(SPI0 TX)を使いました。MCP3008のDOUTとRX、CS/SDNとCsn、CLKとSCL、DINとTXを接続しました。※RX(MISO),TX(MOSI)
接続図

デバイスデータシートの説明

MCP3008の送受信
MCP3008のADCデータを得るタイミングチャートは下図になります。データシートから抜粋しています。
MCP3008タイミングチャート
送受信は大雑把には以下のような感じです。送受信②③は図のように並行して進んでいます。
SPI.write_readinto(buf, read_buf)を使って送受信します。

①デバイスを選択します。
CSを’0’にしてMCP3008を選択します。

②送信信号を送ります。
送信データは3bytesです。スクリプトではbuf=bytearray(3)としました。
StartBitと測定モード、チャンネル情報を送ります。
buf[0] StartBit’0b00000001(0x01)’
buf[1] 測定モードと測定チャンネルを示す|SGL/DIFF|D2|D1|D0|X|X|X|X|を送ります。
buf[2] |X|X|X|X|X|X|X|X| を送ります。
スクリプトでは’X=0’にしています。

③受信信号が戻ります。
受信データも3byteです。スクリプトではr_buf=bytearray(3)としました。
Nullと10bit(B9~B0)データが返ります。
r_buf[0] | ?| ?| ?| ?| ?| ?| ?| ?|
r_buf[1] | ?| ?| ?| ?| ?| 0|B9|B8|
r_buf[2] |B7|B6|B5|B4|B3|B2|B1|B0|

使用するのはr_buf[1]とr_buf[2]です。
スクリプトでは(r_buf[1] & 3) << 8 | r_buf[2]で|B9|B8|B7|B6|B5|B4|B3|B2|B1|B0|の10bitデータにしています。

測定モードと測定チャンネルを示すControlBit(|SGL/DIFF|D2|D1|D0|)は以下のようになっています。
スクリプトでは|SGL/DIFF|の値をconf、チャンネル番号をnumとして、先のbuf[1]を
buf[1]=(conf<<3 | num) <<4 で得ています。
コントロールビット

スクリプト

スクリプトは以下のようにしました。
※開発環境はThonnyです。ThonnyでMicroPythonをRaspberry Pi Pico with RP2040にインストールして使っています。


pico_mcp3008_b2.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from machine import SPI, Pin
# MCP3008 2.7V 8-Channel 10-Bit A/D Converters with SPI Serial Interface
LSB=3300/1024  #3300mV/10bit 

#Chip Select Pin
CS_pin=Pin(1, mode=Pin.OUT, value=1)  #CS GP1
#spi.init
spi = SPI(0, baudrate=1000_000,sck=Pin(2), mosi=Pin(3), miso=Pin(0))

# Chip Select CS(0)
def CS(dat):
    CS_pin.value(dat)
    #CS_pin(dat)

# SGL/DIFF D2 D1 D0 XXXX conf=single(1)/diff(0)
def r_CHN(num, conf=1):
    CS(1)
    buf=bytearray(3)
    buf[0]=0x01
    buf[1]=(conf<<3 | num) <<4 # control bit single/diff|D2|D1|D0|X|X|X|X|
    buf[2]=0x00
    #print(buf)
    r_buf=bytearray(3)
    CS(0)
    spi.write_readinto(buf, r_buf)
    CS(1)
    data=(r_buf[1] & 3) << 8 | r_buf[2]
    data=data*LSB
    print('CH%d='% num, '%5.1f(mV)'%data )
    return data

# TEST ADC 
CS(1)           # CS='1' SHDN
# Single
r_CHN(0)        # CH0
r_CHN(1)        # CH1
r_CHN(2)        # CH2
r_CHN(3)        # CH3

# Diff 
r_CHN(0,0)      # CH0=IN+ CH1=IN-
r_CHN(2,0)      # CH2=IN+ CH3=IN-
r_CHN(3,0)      # CH2=IN- CH3=IN+

CS(1)           # CS='1' SHDN

実行結果

結果は以下のようになりました。※ThonnyのShellに表示されます。
2Vを4分圧しているので500mVづつ変わるハズです。測定できているようです。


pico_mcp3008_b2.py
>>> %Run -c $EDITOR_CONTENT
CH0= 2065.7(mV)
CH1= 1534.0(mV)
CH2= 1031.3(mV)
CH3= 528.5(mV)
CH0= 551.1(mV)      # CH0=IN+ CH1=IN-
CH2= 512.4(mV)      # CH2=IN+ CH3=IN-
CH3=   0.0(mV)      # CH2=IN- CH3=IN+  負になるので
>>> 

まとめ

Raspberry Pi PicoでMCP3008を使ってA/D変換の測定ができました。