
皆さんこんにちは!メカ旦那です。
ADコンバータでよく聞く「MCP3008/3004/3208/3204」 ですが、データシートが英語だし、色々難しい事書かれてるしよくわからない・・・という方も多いのではないでしょうか?そんな方向けにわかりやすく解説してみました。
そもそもADコンバータって何?・・・という方はまずこちらの記事をご覧ください!
MCP3xxx とは
外観
MCP3xxx はアメリカの半導体メーカー「Microchip Technology(マイクロチップテクノロジー)」が作るADコンバータになります。
秋月電子やAmazonなど様々なサイトで販売されており、在庫数も多いため、入手性が良いです。
データシートは秋月電子でダウンロードできますが、英語長文なので読みづらいです。。。そこでそれぞれの特徴を共通点、違いに分けて解説します。
共通点
まずはMCP3xxxの共通点です。

SPIについてはこちらで解説しています!
違い
続いてMCP3xxxの違いはこちらです。

サンプリングレート、分解能はこちらで詳しく解説しています!
通信の流れ
MCP3xxxはセンサ等からアナログ入力を受けた後、AD変換し、コンピュータ等のマスターにSPI出力します。通信の流れについて解説します。


マスター側では関数「spi.xfer2()」を用いる事で、MCP3xxxよりデータを読み取ります。実際の関数の使い方は複雑なため後ほど解説します。
MCP3208とラズパイを繋いでみた
手を動かした方がわかりやすいので、実際にMCP3208とラズパイ3A+を通信してみました。
動画
イメージはこんな感じになります。
可変抵抗からのアナログ出力を、MCP3208でAD変換しラズパイに入力。その後入力データに合わせてラズパイからLEDの明るさを変えるという構成です。
ラズパイにはアナログ入力がない!
今回なぜラズパイと繋いだかと言うと、アナログ入力機能がないからです。
Arduino Unoなど一部のマイコンにはアナログ入力ピンがあり、ADコンバータ不要になります。しかしラズパイ(ピコ以外)は無いため、ADコンバータが無いとアナログ入力を行うことができません。その為今回ラズパイを繋いでみました。

ラズパイにアナログ入力が無い理由についてはこちらをご覧ください!
使用部品
使用するのはこちらです。
部品はまとめて購入することも可能です。
回路
回路図はこちらです。

プログラム マスター側
//ライブラリインポート
import spidev //ラズパイ向けSPIライブラリ
import time
import smbus //ラズパイ向けI2Cライブラリ
//SPI初期設定
spi = spidev.SpiDev()
spi.open(0, 0)
spi.max_speed_hz = 1350000
spi.mode = 0b00 // SPIモード [0,0]
//I2C初期設定
i2c = smbus.SMBus(1)
ARDUINO_ADDR = 0x09 //スレーブ側I2Cアドレス
//アナログ値読み取り関数
def read_adc(channel):
//チャンネル0~7以外はエラー扱い
if channel < 0 or channel > 7:
raise ValueError("channel must be 0-7")
//spi.xfer2の引数作成
byte0 = 0x06 | ((channel & 0x04) >> 2) // スタート(1) + シングルエンド(1) + チャンネル(0)
byte1 = (channel & 0x03) << 6 // チャンネル(1,0 bit目)
byte2 = 0x00
//引数に格納されたデータを出力
//その後スレーブより3byte分の値が戻される為、変数「result」に格納
result = spi.xfer2([byte0, byte1, byte2])
//受領した3byteを12bitに変換
adc_value = ((result[1] & 0x0F) << 8) | result[2]
return adc_value
//メイン処理
try:
while True:
adc_raw = read_adc(0) //引数にチャンネル№(0)を格納し、関数呼び出し
adc_8bit = adc_raw >> 4 //12bit→8bitに変換
i2c.write_byte(ARDUINO_ADDR, adc_8bit) //I2C出力
print(f"Sent : {adc_8bit}") //出力値をシリアルモニタに表示
time.sleep(0.5)
except KeyboardInterrupt:
print("終了しました。")
finally:
spi.close()
プログラムについては、マスター・スレーブそれぞれに書き込む必要があります。まずはマスター側(ラズパイ)のポイントです。


プログラム スレーブ側
//ライブラリインポート
#include <Wire.h> //Arduino向けI2Cライブラリ「Wire.h」をインポート
//初期設定
volatile byte receiveData; //LEDに出力する変数receiveDataを宣言
void setup() {
Wire.begin(9); //Arduinoにスレーブアドレス9を設定
Wire.onReceive(turnOnLED); //マスターからのデータ受信時に関数「turnOnLED」を呼び出す
pinMode(5, OUTPUT); //LEDが接続されている5ピンを出力に設定
}
//呼び出し関数
void turnOnLED(int Number) {
if (Wire.available())
receiveData = Wire.read(); //マスターから受信した数値を変数receiveDataに格納
}
//メイン処理
void loop() {
analogWrite(5, receiveData); //LEDピンに変数receiveDataを出力。つまりPWMでLEDの明るさを制御。
}
続いてスレーブ(Arduino Leonard)側のコードです。ポイントは以下です。

PWMについてはこちらで解説しています!
まとめ
まとめはこちらになります。
この解説が少しでもわかりやすければ幸いです!
コメント