今回は、部品ケースに眠っていた、ADコンバータ(MCP3204)とサーミスタでSPI経由の温度測定を実験します。
Raspberrpi SPIのドキュメントはこちら
回路図です
基準電圧(Vref)にはTL431を使い精度を上げています。
サーミスタの温度変換式
T = 1 / ( log(Rth/R0 ) * 1/B +1/T0 ) - 273.15
MCP3204はSPIインターフェースの4chのADコンバータです。
主な仕様
電源電圧:2.7V~5.5V
分解能:12ビット
入力 :シングルエンド、疑似差動
変換方式:SAR(逐次比較)方式
サンプリング・レート:100ksps
データシートによると、[ 0x06 0x00 0x00 ]の3バイトを送るとCH0の3バイトのデータが返ってきます
新しく作ったユーザーでログインします。
raspi-config でspiを有効にします。
spiが有効になっているか確認
$ls /dev/spi*
/dev/spidev0.0 /dev/spidev0.1
$lsmod | grep spi
spidev 20480 2
spi_bcm2835 20480 0
SPI関連はルート権限が必要なので、spiグループに追加してsudoしなくても動作するようにします。
グループの追加
$sudo gpasswd -a piadmin spi
ターミナルを閉じて再ログインして確認
$groups
piadmin audio spi
ライブラリは、デフォルトでインストール済みのspi-devを使います
MCP3204は 0x06 0x00 0x00 の3バイトを送ると3バイトのデータが返ってきます。そのうち12ビットが有効データとなります。
簡単なテストコード
import spidev spi = spidev.SpiDev() spi.open(0,0) while 1: ad = spi.xfer([ 0x06, 0x0, 0x0]) data = ((ad[1] & 0x0F) << 8) | ad[2] print(data)
トラブル発生
10Kと10Kなので約半分の値が返ってくるはずですが、値がゼロ。
結線を何度も確認しましたが、間違っていないようです。
gpiozeroにMCP3204のクラスがあるので、変更すると正常動作しました。
gpiozeroもデフォルトで入っています。
from gpiozero import MCP3204 import time while 1: adc = MCP3204(channel=0) print(adc) time.sleep(1)
mcp3204シリーズを使うにはgpiozeroは非常に便利ですが、SPI-devが動作しないのは腑に落ちないので色々調べたところ
以下のことが判明しました。
1.Jessie (Raspberian 8)では動作する。
2.Strech(raspberian 9.0)以降では、spi.max_speed_hz を記述しないと動作しない。
正常動作が確認できた、spi-devを使ったサーミスタ温度計測のコードはこちらです。
#!/usr/bin/env python # coding: utf-8 # 3.3V --10K -- Thermista --GND import spidev import math import time spi = spidev.SpiDev() spi.open(0,0) spi.max_speed_hz = 40 * 1000 Vdd = 3.3 Vref=2.495 R0 = 10000 B = 3235 T0 = 298.15 def adc(): sd = spi.xfer2([ 0x06, 0x0, 0]) adc = ((sd[1] &0x0F ) << 8) | sd[2] return adc while 1: Vo = ( adc() / 4096.0 ) * Vref Rth = Vo /(Vdd-Vo) * R0 t= 1 / ( math.log(Rth/R0 ) * 1/B +1/T0 ) - 273.15 print ('{:.2f}'.format( t ) ) time.sleep(1)