2015年5月9日土曜日

ArduinoでSPI通信を使って8チャンネルADC MCP3208からデータを読み取る

複数のセンサからアナログデータを取得してArduinoで処理をする場合のメモです.

ArduinoにはA/D converter (ADC)が6つありますが,これ以上のセンサーからデータを取得する場合,マルチチャンネルADCを使い,ADCとの間はSPI通信を行うことで解決できます.


SPI通信はSerial Peripheral Interfaceの略で, シリアル通信の一種です.これを用いることでArduino側で必要となるピン数を節約できます.

秋月で手に入る8チャンネルADC MCP3208とArduinoとの接続例が公式ページにあるのでこれを元に考えてみます.

MCP3208は1〜8ピンが, 0~7チャネル. 9ピンがDGND, 10ピンはCS, 11ピンがD_IN, 12ピンがD_out, 13ピンがCLK, 14ピンがAGND, 15ピンがV_REF, 16ピンがVDDです.
使用する際は, VDD, V_REFを5Vに接続し, AGND, DGNDをグランドに接続に接続しましょう.
次にMCP3208の10,11,12,13ピンをそれぞれArduinoの10,11,12,13ピンに接続しておきます.

MCP3208のマニュアルによると通信は次のタイミングチャートのように行われるようです.

簡単にまとめるとCSピンをLOWに下げてからCLKを5回アップダウンさせます.ここでシングルエンドもしくは作動モードの指定及び,8チャンネルあるうちのどのチャネルからデータを読み取るかを指定します.続く2回ダミーのアップダウンを後,12回のアップダウンを行っている間にD_outから12ビット分のデータが送られてきます.これに対応するソースコードが先ほどのWebで公開されています.

以下ちょっとソースコードの補足メモを記します.read_adcの関数の中で
byte commandbits = B11000000; //command bits - start, mode, chn (3), dont care (3)
とありますが,これはDinに対する入力ビットを表します.
CS端子(通常High)がLowになったタイミングでADCはDinを読みます.CLKのアップ時にD_INに印加されている電圧を読むことでビットを与えます.
この時のビットが開始ビット, モード指定ビット, チャネル選択ビット(3ビット)と並びます.
開始ビットは1です.
モード指定ビットは1が通常モード, 0が作動モードです. 今回は通常モードで使うので1です.
これがB11となっている理由(始めのBは2進数であることを示します)

次にチャネル番号を指定するために3ビット使います. これは普通に000がチャネル0, 001がチャネル1, 010がチャネル2 ..... 111がチャネル7です.

これらのビットを渡すために, 次に示すようにB11000000というデータに, チャネル番号を3ビット分左にシフトした値との論理和をとり格納しておきます.

 このためには先ほど説明したようにデータを1 bit書き込んではクロックをアップダウンします.
データを送ったあとは, ダミーの2回分のアップダウンを行ったのち,データを読んでいきます
データを読んでからアップダウンを繰り返して1bitづつデータを読んでいます.
この部分で関数の引数をビットシフトしてたし込んでいます.(このソースの後ろの3ビットは必要なさそうですが, byte型を使ったので8bit分明示しているのだと思います)

digitalwriteを1 bitづつ実施してアップダウンを行うことで5bitぶんのデータを入力させます.

最後にソースファイルを実行してオシロスコープでCLKとD_outを出力した結果を見てみます.
 CLKの間隔は結構適当ですがそれなりに動いているのがわかります.
まずはこんなところで







0 件のコメント: