稼働中

Raspberry Pi Pico(d_26)MCP3208 A/D変換

MCP3208 A/D (SPI)

MCP3208はMicrochip社の分解能12bit、8チャンネルA/Dコンバータです。SPI通信で制御します。
Raspberry Pi PicoでMCP3208を使ってみました。

記事(d_07)のMCP3008とほぼ同じです。
MCP3008はADCの分解能が10bitに対して、MCP3208は12bitになっています。PIN配置も同じです。
MCP3208 PIN配置
※Microchip社のデータシートより引用

接続例

MCP3208の動作電圧が2.7~5.5VなのでRaspberry Pi Picoの3.3Vから供給できます。
SPI通信はGP12(SPI1 RX)、GP13(SPI1 CSn)、GP14(SPI1 SCK)、GP15(SPI1 TX)を使いました。MCP3208のDOUTとRX、CS/SDNとCsn、CLKとSCL、DINとTXを接続しました。
可変抵抗で調整した2Vを4分割してMCP3208のCH0~CH3に入力しました。
MCP3208 接続図

MCP3208の説明

データシートから抜粋してMCP3208の説明します。
SPI通信は以下のようになっています。CS=’0’でアクティブです。3bytesを伝送します。

下方のスクリプトでは、送信データbuf=bytearray(3)、受信データr_buf=bytearray(3)を
spi.write_readinto(buf, r_buf)
で行っています。

送信データはStartBit’1’、ControlBit(|SGL/DIFF|D2|D1|D0|)を送ります。
SGL/DIFFは測定モードでsingle-ended’1’、differntial’0’です。
|D2|D1|D0|はADCのChannel CH0-CH7(Pin 1-8)です。
※詳細はデータシートを参照ください。

送信データbufを
buf[0]=(0b100)|(SGL/DIFF)<<1)|(|D2|D1|D0|>>2)
buf[1]=(|D2|D1|D0|<<6) & 0xc0
buf[2]=0x00
としました。

12bitのADCデータは受信データr_bufから
(r_buf[1] & 0x0f) << 8 | r_buf[2]
で得られます。
この値にVREF/4096を乗じて電圧値に換算します。※VREFとVDD(3.3V)を接続しています。
MCP3208 SPI
※ Microchip Technology MCP3208のデータシートから抜粋

スクリプト

MCP3208のスクリプトは以下のようにしました。
※開発環境はThonnyです。ThonnyでMicroPythonをRaspberry Pi Pico with RP2040にインストールして使っています。
※Raspberry Pi Pico単独で動作させるには’main.py’としてRaspberry Pi Picoにuploadして使います。


pico_MCP3208_test_01b.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from machine import SPI, Pin
# MCP3208 2.7V 8-Channel 12-Bit A/D Converters with SPI Serial Interface
LSB=3300/4096       #3300mV/12bit 
#Chip Select Pin
CS_pin=Pin(13, mode=Pin.OUT, value=1)  #CS GP1
#spi.init
spi = SPI(1, baudrate=100_000,sck=Pin(14), mosi=Pin(15), miso=Pin(12))

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

# num=Channel conf=single-ended(1)/differential(0) 
def r_CHN(num, conf=1):
    CS(1)
    buf=bytearray(3)
    # |Start bit(1)|SGL/DIFF(1/0)|D2|(|D2|D1|D0|>>2)
    buf[0]= 4|(conf<<1)|(num>>2) 
    #|D1|D0|X|X|X|X|X|X| 
    buf[1]=(num<< 6) & 0xc0   #0b11000000 = 0xc0
    buf[2]=0x00               # don't care
 
    r_buf=bytearray(3)
    CS(0)
    spi.write_readinto(buf, r_buf)
    CS(1)
    data=(r_buf[1] & 0xf) << 8 | r_buf[2] #0b1111(15)0xf

    data=data*LSB       # mV
    print('CH%d='% num, '%5.1f(mV)'%data )
    return #data

## example
CS(1)    # CS='1' SHDN
#r_CHN(num, conf=1) Channel_num,SGL(default=1)/DIFF(0)
# 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

関数 部分説明

r_CHN(num, conf=1)
num:測定Channelです。 0~7
conf:測定モードです。single-ended(1)、differential(0)

実行結果

結果は以下のようになりました。※Thonnyのshellに表示されます。
各CHは2.0V/4=500mVになっています。正常に測定できているようです。


>>> %Run -c $EDITOR_CONTENT
CH0= 2050.4(mV)
CH1= 1536.4(mV)
CH2= 1025.6(mV)
CH3= 507.6(mV)
CH0= 511.6(mV)
CH2= 510.0(mV)
CH3=   0.0(mV)      #マイナスになるので
>>> 

まとめ

Raspberry Pi PicoでMCP3208を使ってD/A変換ができました。