今日のゴール
アナログ値をデジタル値に変換する
"AD変換"
本記事の登場人物
主役
彼らがAD変換の主役です。本記事で解説します。
-
12ビットADコンバータ MCP3208-CI/P x 1
- アナログ値をデジタル値に変換します
-
半固定抵抗 x 1
- 抵抗値を変化させアナログ値をセンシングします
-
フォトレジスタ x 1
- 抵抗値を変化させアナログ値をセンシングします
脇役
ちなみに彼らも必要ですが、本記事では解説しません。
- RaspberryPi一式
- 抵抗(330Ω) x 1
- 赤色LED x 1
- ブレッドボード x 1
- ジャンパワイヤ
- オス-メス x 1セット
- オス-オス x 1セット
AD変換とは?
アナログ値をデジタル値に変換します。
なぜデジタル値が必要なのか?
RaspberryPiへの入力は基本的には、2進数として、LOW(0)/HIGH(1) 2つの状態のどちらかになる。
これは、部屋の明るさだと、明かりがついているか消えているか、の2段階として理解します。
↓
これをデジタル値、0-4095のような段階的な値として入力することを狙います。
そもそもアナログ値、デジタル値って?
- アナログ値
- 連続値
- e.g. 明るさ、温度、電圧など
- デジタル値
- 飛び飛びの値(離散値)
- e.g. 計測して桁を切り捨てた値(デジタル時計)など
AD変換 (画像引用元: Raspberry Piで学ぶ電子工作|ブルーバックス)
-
- センサからのアナログ値の取得
-
- AD変換
-
- デジタル値の通信
1. センサからのアナログ値の取得:
特定の地点での抵抗値を変化させ、端子から出力させるアナログ電圧を変化させる(0V-3.3V)1.65V
- 半固定抵抗
- フォトレジスタ (CdSセル)
半固定抵抗?
画像引用元: akizukidenshi.com
- 可変抵抗の一つで抵抗の大きさを調整可能
フォトレジスタ (CdSセル)?
画像引用元: akizukidenshi.com
2. AD変換
アナログ電圧を測定しその値を、ADコンバータにてAD変換しデジタル値にする(0-4095->12bit) 2048
- ADコンバータ
ADコンバータ?
(12ビットADコンバータ MCP3208-CI/P)
画像引用元: akizukidenshi.com
ADコンバータ特徴
- 16ピンを持つ回路
- 0ch-7chの8つのアナログ値を読み取れるチャネル
- アナログ値をデジタル値に変換する
- 12ビット精度で送れる
- $2^12=4096=4*10^3$
3. シリアル通信
デジタル値を2進数 (1000_0000_0000 = 2048) としてSPI通信で送る
- SPI通信
- I2C通信
3. シリアル通信
code
# MCP3208からSPI通信で12ビットのデジタル値を取得。0から7の8チャンネル使用可
def readadc(adcnum, clockpin, mosipin, misopin, cspin):
if adcnum > 7 or adcnum < 0:
return -1
GPIO.output(cspin, GPIO.HIGH)
GPIO.output(clockpin, GPIO.LOW)
GPIO.output(cspin, GPIO.LOW)
commandout = adcnum
commandout |= 0x18 # スタートビット+シングルエンドビット
commandout <<= 3 # LSBから8ビット目を送信するようにする
for i in range(5):
# LSBから数えて8ビット目から4ビット目までを送信
if commandout & 0x80:
GPIO.output(mosipin, GPIO.HIGH)
else:
GPIO.output(mosipin, GPIO.LOW)
commandout <<= 1
GPIO.output(clockpin, GPIO.HIGH)
GPIO.output(clockpin, GPIO.LOW)
adcout = 0
# 13ビット読む(ヌルビット+12ビットデータ)
for i in range(13):
GPIO.output(clockpin, GPIO.HIGH)
GPIO.output(clockpin, GPIO.LOW)
adcout <<= 1
if i>0 and GPIO.input(misopin)==GPIO.HIGH:
adcout |= 0x1
GPIO.output(cspin, GPIO.HIGH)
return adcout
inputVal0 = readadc(0, SPICLK, SPIMOSI, SPIMISO, SPICS)
演習1
> 画像引用元: [Raspberry Piで学ぶ電子工作|ブルーバックス](http://bluebacks.kodansha.co.jp/special/rspi1.html)06-01-print.py
while True:
inputVal0 = readadc(0, SPICLK, SPIMOSI, SPIMISO, SPICS)
print(inputVal0)
演習2
> 画像引用元: [Raspberry Piで学ぶ電子工作|ブルーバックス](http://bluebacks.kodansha.co.jp/special/rspi1.html)06-02-led.py
while True:
inputVal0 = readadc(0, SPICLK, SPIMOSI, SPIMISO, SPICS)
if inputVal0 < 2000:
GPIO.output(LED, GPIO.HIGH)
else:
GPIO.output(LED, GPIO.LOW)
演習3
06-03-volume.py
while True:
inputVal0 = readadc(0, SPICLK, SPIMOSI, SPIMISO, SPICS)
vol = "{0}%".format(int(inputVal0*100/4095))
if vol != vol_old:
print(vol)
args = ['amixer','-q','cset','numid=1',vol]
subprocess.Popen(args)
vol_old = vol
まとめ
- AD変換することで、センサーに入力されたアナログ値をデジタル値として回路から利用することができる
- AD変換はADコンバーターを使って行う
- デジタル値の通信はSPI通信でおこなう
なお、AD変換の仕組みはRaspberry Piで学ぶ電子工作(ブルーバックス)にわかりやすくまとまっているので、みなさん買って読みましょう。