4
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

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

Last updated at Posted at 2019-12-06

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

#構成
aaa.jpg

  • 雑ですみません、ワイヤに隠れてしまっていますが左下の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

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

mcp3208.py
import RPi.GPIO as GPIO
from time import sleep

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

def sendToMCP3208():  #制御手順3
    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(): #制御手順5
    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():  #制御手順6
    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

#参考
講談社 RaspberryPiで学ぶ電子工作 著者:金丸隆志

4
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?