RaspberryPiとMCP3208でAD変換するソースの説明

#概要
7ch 12bits ADコンバータICであるMCP3208を、RaspberryPiとPython、ボリューム抵抗を用いて利用する方法は、各種書籍に例がありますがデータシートと突き合わせてみて分からない事が多かったので、データシートを読み込み、分かった事を記事にしてみました。

#構成
![aaa.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530581/bf34dbf8-acf6-2e48-5402-c8dafc5d582e.jpeg)

* 雑ですみません、ワイヤに隠れてしまっていますが左下のDIP ICがMCP3208で、Raspberry Piと接続しています。SPICLK⇔CLK、SPIMOSI⇔DIN、SPIMISO⇔DOUT、SPICE0⇔CS
* MCP3208のCH0には3.3Vを接続したボリューム抵抗を接続しています。
* 12bitなので4095階調、値が0なら0.0V、2048なら1.65V、4095なら3.3Vのように読み替えます。


#MCP3208制御の手順
1. 基本的にSPIインタフェースで通信をするので、下図のように信号をやりとりすればAD変換ができます。初期ステートはCS=High、CLK=LOWです。CS=Lowにすると処理を開始できます。(CLKはHIGHでアイドル状態でも問題ありません)

2. MCP3208へのコマンド入力をすると、MCP3208はDout端子から12bitのデータを吐き出します。MCP3208は__コマンド入力はクロックの立ち上がりエッジで認識__、__データ出力はクロックの立下りエッジで出力される__ことを理解してデータシートを読むとわかりやすいです。（間違ってたら指摘お願いします）
3. まずは下図のMCU Transmitted Dataとある一番左の8bitデータを見ると、MSBから0が5つ並んでいます。次にスタートビット1、Single-endedモードの1、チャンネルを指定する3ビットの3ビット目(チャンネル0なら000なので0)が記載されており、クロックの立ち上がりで1ビットずつMCP3208へ入力がされていきます。※実は0が5つ並んでいるのは入力する必要がありません。データシートにはSPIは8ビット単位で通信する事が多いので0パディングするといいよとのことだけなので、各種書籍にはこの0をスルーしていますが、今回はこの図を忠実に再現してみます。
 
4. 次に一つ右の8bitデータを見ると、チャンネル指定ビットの2ビット目と1ビット目をD1、D0に入れます。（チャンネル0なら000なので00）残りの6ビットは使いません。

5. 0 5つを含めた10bitをMCP3208へ入力が完了タイミングは図のクロック10の数字文字の左の立ち上がりエッジになります。Doutから出力がはじまるのは、次の11クロック目の立下りエッジです。それから出力データ1+12ビットが出力されますが、最初の1ビットはnullビットなので対象外処理をする必要があります。

6. 12ビットを受信し終わったらCSをHIGHにしてAD変換の1処理を完了します。

> MCP3208データシート P21抜粋
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530581/9cf61921-612e-302e-5aad-ab24b657c462.png)




#ソース
上記制御手順と照らし合わせてみてください。説明の便宜上、まわりくどい記載になっているので、実用的なソースは各種書籍記載のソースを参考にしてください。

```python:mcp3208.py
import RPi.GPIO as GPIO
from time import sleep

def initialize():  #制御手順１
    GPIO.output(SPICE0,GPIO.HIGH)  #このHigh、Lowで1クロックを再現
    GPIO.output(SPICLK,GPIO.LOW)

def sendToMCP3208():  #制御手順３
    GPIO.output(SPICE0,GPIO.LOW)

    Transmitted_Data1 = 0b00000110 #10ビット中この8ビットを最初に入力する

    for i in range(8):
        if Transmitted_Data1 & 0b10000000: #MSBが1ならTrue
            GPIO.output(SPIMOSI,GPIO.HIGH) #1をセット
        else:
            GPIO.output(SPIMOSI,GPIO.LOW)#0をセット
        GPIO.output(SPICLK,GPIO.HIGH)#クロック出力して1bit入力
        GPIO.output(SPICLK,GPIO.LOW)
        Transmitted_Data1 = Transmitted_Data1 << 1 #1bit左シフトする事で、if判定時に次のビットを操作対象にできる

    #制御手順4
    Transmitted_Data2 = 0b00000000 #10bit中の2ビット、上位2ビットだけ使用
    for i in range(2):
        if Transmitted_Data2 & 0b10000000:
            GPIO.output(SPIMOSI,GPIO.HIGH)
        else:
            GPIO.output(SPIMOSI,GPIO.LOW)
        GPIO.output(SPICLK,GPIO.HIGH)
        GPIO.output(SPICLK,GPIO.LOW)
        Transmitted_Data2 = Transmitted_Data2 << 1



def receiveFromMCP3208(): #制御手順５
    Received_Data = 0b000000000000 #戻り値の12bitデータ変数
    for i in range(13):  #iは0→12まで1ずつインクリメントされる
        GPIO.output(SPICLK,GPIO.HIGH)
        GPIO.output(SPICLK,GPIO.LOW)

        if i == 0: #nullビットなので対象外処理
            pass
        elif i >=1 and i <= 11: #通常処理
            Received_Data = Received_Data | GPIO.input(SPIMISO)
            Received_Data = Received_Data << 1
        elif i== 12: #最終ビットの場合左ビットシフトをしない
            Received_Data = Received_Data | GPIO.input(SPIMISO)

    return Received_Data

def close():  #制御手順６
    GPIO.output(SPICE0,GPIO.HIGH)


SPICLK = 11
SPIMOSI = 10
SPIMISO = 9
SPICE0 = 8
GPIO.setmode(GPIO.BCM)
GPIO.setup(SPICLK,GPIO.OUT)
GPIO.setup(SPIMOSI,GPIO.OUT)
GPIO.setup(SPIMISO,GPIO.IN)
GPIO.setup(SPICE0,GPIO.OUT)


while True:
    initialize()

    sendToMCP3208()

    value = receiveFromMCP3208()
    print value

    close()

    sleep(0.2)
```

#ロジアナ計測
本ソース実行時の計測結果です。コンソール出力値は約2450。入力時はクロックの立ち上がりで00000110 00が入力されている事が分かりますね、8bitと2bitの間に時間がかかってます。出力時はクロックの立下りで100110010100、これは10進数で2452なのでコンソール出力値と当然ですがあっています。ボリューム抵抗の実測値は1.973Vだったので、4095*1.973V/3.3V≒2448でAD変換が問題なくできている事がわかりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530581/a5731207-7dfa-6875-8475-5ecc724b3cc0.png)


#参考
[講談社 RaspberryPiで学ぶ電子工作 著者：金丸隆志](https://www.amazon.co.jp/%E3%82%AB%E3%83%A9%E3%83%BC%E5%9B%B3%E8%A7%A3-Raspberry-Pi%E3%81%A7%E5%AD%A6%E3%81%B6%E9%9B%BB%E5%AD%90%E5%B7%A5%E4%BD%9C-%E4%BD%9C%E3%81%A3%E3%81%A6%E5%8B%95%E3%81%8B%E3%81%97%E3%81%A6%E3%81%97%E3%81%8F%E3%81%BF%E3%81%8C%E3%82%8F%E3%81%8B%E3%82%8B-%E3%83%96%E3%83%AB%E3%83%BC%E3%83%90%E3%83%83%E3%82%AF%E3%82%B9/dp/4062579774/ref=asc_df_4062579774/?tag=jpgo-22&linkCode=df0&hvadid=295662004514&hvpos=1o1&hvnetw=g&hvrand=3529677763044198059&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=1009283&hvtargid=pla-527103853915&psc=1&th=1&psc=1)